- extern
- 指针
- 1. *(p++)与*(++p)
- 2. 指针传参
- 3. 数组与指针
- 4. 指针与常量
- 函数
- 结构体
- typedef
- 声明与定义
- attribute机制
extern 除了可以让全局变量作用域拓展到其他文件,还能在一个文件内让全局变量拓展到整个文件。如
int main(int argc, char *argv[])
{
//a的作用域原本在它声明的后方
//没有extern就用不了a
extern int a;
a = 3;
printf("a:%dn",a);
return 0;
}
int a; //全局默认初始化为0
结果
明确自加的顺序。P++是先用了后加,++p是先加了后用*(p++):先取p,用了之后,再偷偷加1,(++p):p先加1,再用
int main(int argc, char *argv[])
{
int array[6] = {6,5,4,3,2,1};
int *p1 = array, *p2 = array;
printf("*(p++):%dn", *(p1++));//相当于*p1,即a[0]
printf("*(++p):%dn", *(++p2));//相当于*(p2+1),即a[1]
//p1用完之后偷偷自加,所以现在只想a[1]
printf("after p1:%dn", *p1);
printf("after p2:%dn", *p2);
return 0;
}
结果
函数传参是采用“值传递”。当参数是指针的时候,可以改变指针变量指向的变量的内容(即可以用解引用改变值),但不能改变指针变量所指向的地址。如
void func(int *p)
{
*p = 5;
p= (int *)12345;
}
int main(int argc, char *argv[])
{
int a=22, *p=&a;
printf("before p:%pn", p);
func(p);
printf("a:%dnafter p:%pn", a,p);
return 0;
}
结果
题外:
void func(int *p)
{
p (int *)12345;
*p = 5;
}
这样是会出现段错误的。原因在于:对于可访问的内存地址才有资格去修改它的值,不可访问的内存是不能修改它的值。在这里它先修改了p所指向的地址,使p指向了一个未知的、不可访问的内存,然后再解引用自然是不可以的。
3. 数组与指针char *p1 = "hello"; //√。让p1指向hello这个常量
char arr[10]; //×。这种错误就像 int a[10];
arr = "hello"; // a={10,9};
return 0;
char *p1 = "hello"; char arr[] = "hello"; p1[2] = 'a'; //×。 arr[2] = 'a'; //√。 return 0;
当指针指向字符串常量的时候,不能通过指针去修改
4. 指针与常量int arr[6] = {1,2,3,4,5};
int *p = &(arr[0]+2);
结果:编译报错
原因分析
a[0] = 0,程序的原意是想将p的解引用变为2,但这样子做是不对的。因为不能够给一个常量取址。编译器不再把arr[0]+2看作是一个变量,而是一个常数
int p = &(arr[0]+2); 等价于 intp = &2; 这两个写法都是不对的
int p = &(arr[0]+arr[2]); 等价于 int p = &2; 也是不对的。
int p =&(arr[0]+0); 不等价于 int p = &(arr[0]); 等价于 int * p = &(0);因为编译器已经把arr[0]+0 看做一个常数0
int * p = &(arr[0]); 这个是合法的,这个时候把arr[0]看成一个变量
函数函数名代表函数的起始地址。如:
//功能:func1为带参函数,带的是函数指针。通过这个函数指针调用func2
void func1(void (*func2)(void));
void func2(void);
int main(int argc, char *argv[])
{
func1(func2);//以func2作为函数指针
return 0;
}
void func1(void (*func2)(void))
{
printf("have used func1n");
func2();
}
void func2(void)
{
printf("have used func2n");
}
结果
同类的结构体变量可以相互赋值
结构体作为参数也是进行“值传递”,即还是会有形参实参之分,而且开销大,最好用指针的形式
typedef a b 把a这种数据类型取别名b
#define a b 把b用a来替换
typedef结构图的时候,结构体可以没有类型名。
typedef struct node
{
int a;
char b;
float c;
} my_struct;
等价于
typedef struct
{
int a;
char b;
float c;
}my_struct;
typedef书写指南
1、按照定义变量形式写出来
2、变量名改成类型名
3、往最前加上typedef
例子:
① int [10] 被typedef为Num 1 :int a[10] 2 :int Num[10] 3 :typedef int Num[10] ② int (*)(void) 被typedef 为Pointer 1 :int (*p)(void) 2 :int (*Pointer)(void) 3 :typedef int (*Pointer)(void)声明与定义
在C中,声明通常伴随着定义。
int a; 这里不仅有声明,还有定义。 extern int a; 这里只有声明 int a = 0; 声明、定义、初始化(定义之后同时赋值)。 int a; a=0; 声明、定义,然后赋值
声明不需要开辟新内存,定义则需要
attribute与它要限制的东西之间不宜加括号。如:
int num attribute((aligned(10241024))) ;
不能够写成:( int num attribute((aligned(10241024))) );
attribute((force))
作用是表示所定义的变量类型是可以做强制类型转换的,且让编译器不会发出警告。(但是亲测还是会)。
使用方法是:放在数据类型前面。如:
int a = 99;
int *p = __attribute__((force) int *)a;
printf("%pn",p);
结果



