num[3][3]={1,2,3,4,5,6,7,8,9}
num[1][-2]==num[0][1]==2:
取某个元素时,是先通过计算这个元素的地址,再通过计算得来的地址取得该元素的。设数组a[rows][cols](即有rows行,cols列),a[i][j]的地址为 a + i*cols + j, 所以num[1][-2]的地址为 num+1乘3-2=num+0乘3+1.与num[0][1]的地址一样。值为2;
(-1)[nums][5]看成nums[-1][5]值和nums[0][2]一样
-1[nums][5]看成-(1)nums[5]即-nums[1][5]=-nums[2][2]=-9
strlen是一个函数,只能以字符串做参数
sizeof运算符,可以函数做参数,返回其操作数的大小,即size_t类型的值,以字节为单位,这是一个无符号整型.
sizeof 后面的内容在编译时就已经完成了
int main(int argc, char *argv[])
{
int a[3][2] = { 2, 0, 1, 8 };
char *str = (char *)malloc(sizeof(char) * 20);
printf("%d\n",nums[1][-2]););
strcpy(str, "\0101\\xb2");
printf("%zu\n", sizeof(a));
printf("%zu %d\n", sizeof(a[1][1] =0), a[1][1]);
printf("%zu %zu\n", sizeof(str), strlen(str));
}
输出
24
4 8
8 6
sizeof(a)=6*4=24;
sizeof 是在编译阶段已经计算出来,而赋值是在运算过程中的,所以a[1][1]=0不会执行。输出4 8;
这里字符指针变量str用malloc动态开辟出来了一片有20个字节大小的空间,sizeof()计算 str 这个指针变量的长度为8,而strlen()函数计算的则是str指向字符串的长度。
把局部变量改变为静态变量后是改变了它的存储方式,即改变了它的生存期。
1.普通局部变量:存储于栈中,使用完毕会立即释放
被 static 修饰的变量总是存在内存的静态区
2.自动变量会随着函数被调用和退出而存在和消失,而static类局部变量不会,它不管其所在的函数是否被调用,都将一直存在
把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围
1.全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同
2.非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。
静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。
static静态函数:使函数的作用域仅局限于本文件,即内部函数。
static int a = 2018;
static void func(void)
{
static int b;
printf("a = %d, b = %d\n", a++, ++b);
}
int main(int argc, char *argv[])
{
func( );
func( );
func( );
}
一、预编译:主要处理源代码文件中的以“#”开头的预编译指令。
1.删除所有的#define,展开所有的宏定义。
2.删除所有的注释,“//”和“/**/”。
…
二、编译:进行一系列词法分析语法分析、语义分析及优化后,生成相应的汇编代码文件。
1.词法分析 2. 语法分析 3. 语义分析 4. 优化 5. 目标代码生成 6. 目标代码优
三、汇编:将汇编代码转变成机器可以执行的指令(机器码文件)
四、链接
1.const int *p :*p指向的内容无法改变
2.int const *p:*p指向的内容不可改变
3.int * const p: *p不能改变指向,值可以变
4.const int *const p:即不改变指向也不改变内容
char y[ ] = "XiyouLinuxGroup",x[ ] = "2018";
char *const p1 = y;
const char *p2 = y;
/* (1) */ p1 = x;
/* (2) */ p2 = x;
/* (3) */ *p1 = 'x';
/* (4) */ *p2 = 'x';
1,4错误
2,3正确
总结:
如果const在 * 的左侧,则const用来修饰指针所指向的变量,即指针指向位常量;
如果const位于 * 的右侧,则const就是修饰指针本身,即指针本身就是常量。
const与#define区别
1.#define 宏是在预编译阶段进行替换,而 const 修饰的只读变量是在编译的时候确定其值
2…#define 宏没有类型,而 const 修饰的只读变量具有特定的类型
int main(int argc, char *argv[])
{
int a[5];
printf("%p\n", a);
printf("%p\n", a+1);
printf("%p\n", &a);
printf("%p\n", &a+1);
}
结果(不同计算机 结果可能不同)
0x7ffdcd368b20
0x7ffdcd368b24
0x7ffdcd368b20
0x7ffdcd368b34
a即a[0]的地址。 a+1取的是a[1]的地址,即在数组首地址上加上一个int型大小空间。
&a取的也是数组首地址 。 &a+1中的&a代表整个数组, +1后就是跳过这个数组,即加上5个int大小的空间
int main(int argc, char argv[]){/…*/}
程序由主函数开始运行,由主函数结束,主函数可调用任何函数,任何函数都不可以调用主函数
argc:参数的个数。argv[]:是一个字符指针数组,每一个元素指向一个字符串。argv[0]:指向程序的路径名,argv[1…]:指向第n个参数对应的字符串
int f(unsigned int num)
{
for (unsigned int i = 0; num; i++)
num &= (num - 1);
return i;
}
&运算符,两个数对应的二进制位都为1结果为1 ,否则 为 0
第一次循环num=2018&2017等价于11111100010&11111100001 结果为11111100000,即 num = 2016
第二次循环num=2016&2015等价于11111100000 & 11111011111 结果为 11111000000,即num=1984
第三次循环num=1984&1983等价于11111000000&11110111111结果为11110000000,即num=1920
int main(int argc, char *argv[])
{
char n[] = { 1, 0, 0, 0 };
printf("%d\n", *(int *)n);
}
强制转换为int*类型,按大小端模式读出,如果是小端就是0000 0000 0000 0000 0000 0000 0000 0001
对齐规则
1.第一个成员在与结构体变量偏移量(offset)为0的地址处。
2.其他成员变量要对齐到对齐数的整数倍的地址处。
(1)对齐数 = 对齐系数 与 该成员大小的较小值。
(2)#pragma pack(n);中的n就是对齐系数。
(3)VS中默认的值为8;linux中的默认值为4。
3.结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
struct icd {
int a;
char b;
double c;
};
struct cdi {
char a;
double b;
int c;
};
int main(int argc, char *argv[])
{
printf("%zu %zu\n", sizeof(struct icd), sizeof(struct cdi));
}
16 24
举个例子:
1.下面的结构体大小分别是多大(假设32位机器)?
struct A {
char a; //1
char b; //1
char c; //1
};
//进行整体对齐,最大类型为1<对齐系数4,按1整体对齐,所以1+1+1=3
struct B {
int a; //4
char b; //1
short c;//2
};
//进行整体对齐,最大类型为4=对齐系数4,所以按4整体对齐4 1+2=3<4 对齐4 所以4+4=8
struct C {
char b; //1
int a; //4
short c;//2
};
//进行整体对齐,最大类型为4=对齐系数4,所以按4整体对齐 1<4(对齐4) 4=4 2<4(对齐4) 所以4+4+4=12
#pragma pack(2)
struct D {
char b; //1
int a; //4
short c;//2
};
//进行整体对齐,最大类型为4>对齐系数n(2),所以按2整体对齐 1<2(对齐2)4>2(2的倍数) 2=2 所以2+4+2=8
答案及解析:3 8 12 8
2. 有一个如下的结构体:
struct A{
long a1;
short a2;
int a3;
int *a4;
};
请问在64位编译器下用sizeof(struct A)计算出的大小是多少?
24
28
16
18
答案及解析:24
64位编译器下:指针8字节(一定不能忘记),题目不说默认4字节对齐
long a1; //8
short a2; //2 8+2=10(不是4的倍数)对齐到4的倍数12
int a3; //4 4+12=16(4的倍数)
int *a4; //8 8+16=24(4的倍数)