1.指針的定義
指針就是內存地址,指針變量就是存儲地址的變量
聲明:數據類型: *指針變量的名字
int * p;
初始化:int *p = NULL;//空,0.0 \0 空指針
int i =10;
int *p;
p = &i;
printf("addr: &i=%p p=%p\n",&i, p);
printf("value: i=%d *p=%d\n",i, *p);
指行結果:
addr: &i=0x7fff2d938e9c p=0x7fff2d938e9c
value: i=10 *p=10
2.指針作爲返回值
指針用作函數的返回值,表示返回一個地址
注意:不要返回自動變量的地址,自動變量在函數結束後使用的內存會被釋放
int *test(int n){
int *p = &n;
return p;
}
3.指針作爲函數的參數
函數可以接受一個地址作爲參數,函數可以修改實參的值,因爲指向地址的內容被修改了.
void swap(int *a,int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
4.字符串的表現形式
在C語方中,沒有string類型
字面值常量:”abcdef”以’\0’結束,存在於全局區,不可以改變
char arr[]:表示字符串類型的變量,後面加’\0’,存在於內存中函數棧,值可以改變
char * 指針存儲地址,可以指向字面值,也可以指向char數組裏面的無素
5.操作字符串的函數庫
位於string.h裏,在linux內核中源碼實現存在於lib/string.c
/**
* strcpy - Copy a %NUL terminated string
* @dest: Where to copy the string to
* @src: Where to copy the string from
*/
char *strcpy(char *dest, const char *src)
{
char *tmp = dest;
while ((*dest++ = *src++) != '\0')
/* nothing */;
return tmp;
}
/**
* strcat - Append one %NUL-terminated string to another
* @dest: The string to be appended to
* @src: The string to append to it
*/
char *strcat(char *dest, const char *src)
{
char *tmp = dest;
while (*dest)
dest++;
while ((*dest++ = *src++) != '\0')
;
return tmp;
}
/**
* strlen - Find the length of a string
* @s: The string to be sized
*/
size_t strlen(const char *s)
{
const char *sc;
for (sc = s; *sc != '\0'; ++sc)
/* nothing */;
return sc - s;
}
/**
* strcmp - Compare two strings
* @cs: One string
* @ct: Another string
*/
int strcmp(const char *cs, const char *ct)
{
unsigned char c1, c2;
while (1) {
c1 = *cs++;
c2 = *ct++;
if (c1 != c2)
return c1 < c2 ? -1 : 1;
if (!c1)
break;
}
return 0;
}
6.結構體
結構體:不同類型數據的集合
成員可以具有不同的類型
每個成員都有名字,通過名字來訪問成員
使用一個結構體變量之前,必須先進行類型定義
typedef:給類型起別名
typedef struct
{
成員列表;
}別名;
#include <stdio.h>
#include <string.h>
typedef struct{
int id;
char name[20];
char sex;
int age;
} student;
int main(){
student s;
s.id = 1;
strcpy(s.name, "bshui");
s.sex = 'M';
s.age = 18;
printf("id:%d name:%s sex:%c age:%d\n",s.id,
s.name, s.sex, s.age);
return 0;
}
運行結果:
id:1 name:bshui sex:M age:18
7.結構體作爲函數的參數與返回值
如果使用結構體作爲函數的參數與返回值會佔用大量的內存,會消耗大量的時間
一般使用結構體指針作爲函數的參數和返回值,提高程序的效率
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct{
int id;
char name[20];
char sex;
int age;
} student;
void show_info(student *s);
int main(){
student *s = (student *)malloc(sizeof(student));
s->id = 1;
strcpy(s->name, "bshui");
s->sex = 'M';
s->age = 18;
show_info(s);
return 0;
}
void show_info(student *s){
printf("id:%d name:%s sex:%c age:%d\n",s->id,
s->name, s->sex, s->age);
}
運行結果:
id:1 name:bshui sex:M age:18
8.結構體的對齊與補齊
對齊:內存分配將結構體中的成員分配到內存的邊界上,方便訪問,每個成員都是從自身長度的整數倍開始存放
補齊:整個的結構體長度必須保持爲內部最長成員的整數倍
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int i; // 4
short sh;//2
char c; //1
double d; //8
} s;
typedef struct{
char a; //2
short b; //2
char d; //2
} t;
int main(){
s s1;
t t1;
//對齊
printf("t:%ld\n", sizeof(t1));
//補齊
printf("s:%ld\n",sizeof(s1));
return 0;
}
執行結果:
t:6
s:16
9.聯合體
可以有多個不同類型的成員組成
通過成員的名字訪問成員
所有成員共用起始地址相同的一段內存
大端:低位字節存儲高位數據
小端:低位字節存儲低位數據
#include <stdio.h>
int main(){
union{
int i;
char c;
}u;
u.i = 1;
if(u.c==1)
printf("little end\n");
else
printf("big end\n");
return 0;
}
10.指針類型區分
int i:定義一個整型變量
int *q; q是一個指向整型變量的指針
int a[n]; a數組,包含n個整型的元素
int *q[n]; q數組,包含n個元素每個元素都是指向整型數據的指針
int (*q)[n]; q指針,指向一個數組,可以包含n個整型元素
int f(); f函數,返回值類型爲int
int *f(); f函數,返回值類型指向整型數據的指針
int (*f)(); f函數指針,指向一個函數,函數返回值爲int
itn **q; q指針,指向一個指針