C补习问题汇总
2023年2月6日加入成都华清远见进行嵌入式开发的学习,期待能够学到更多的知识,找到一份满意的工作。
问题1:关于C虚拟内存的问题?(已解决)
描述:
-
已知C语言的虚拟内存中存在栈、堆、静态区、常量池、代码区等,自己定义变量的值为常量;若定义int a = 10;char ch = ‘d’;
-
其中10和‘d’是存储在堆中还是静态常量池中,或者就在栈中?如图:
PS:之前一直认为是存储在堆中,只用使用const关键字定义的变量才会存储在常量池中。
-
**答:**C的虚拟内存图与Java不一致,在C中使用int等基本数据类型定义的变量会存放在栈中(包括地址和数据)。C的堆中存放的是malloc()、calloc()、free()函数操作的内存,即程序员自己定义申请操作的空间和变量。而常量区只读,不能写入,所以此处是存放在栈中。
问题2:String不可变问题?(已解决)
描述:
-
定义字符串char[5] strs = “abcd”,已知字符串是存储在常量池中,为什么说字符串String不可变?
**答:**当修改strs字符串时,修改的是strs存储的地址,而在常量池中的字符串"abcd"并未改变。当函数结束,自动销毁。
问题3:数据在内存中存储的方式?(已解决)
描述:
-
已知数据在计算机都是以二进制的形式存储,具体内容(源码、反码、补码)?
**答:**具体内容为二进制的补码,即所有数据是以二进制的补码存储。
PS:正数的源码、反码、补码相同;负数以源码-反码-补码的顺序转化
问题4:浮点型数据的二进制存储形式?(难点)
描述:
-
已知所有数据是以二进制的形式存储,定义float f = 1.23;double d = 2.46;
-
浮点数据小数部分的数据二进制的存储形式?
问题5:printf输出格式符?(已解决)
描述:
-
已知printf(“输出格式符”)中有i、d、o、x、u、c、s等。
-
当输出格式符中出现其他字符时,如printf(“%5d”,12)。
答:%5d指的是总的打印长度为5,这里输出" 12",12占两位,填充3个空格。
问题6:default放在中间?(已解决)
描述:
-
当使用switch时,default放在中间,若default前面的case都不满足,是否还会检索default后面的case选项?
**答:**还会检索default后面的case,并且后面的case选项也都不满足switch再执行default的代码块。并且当没有break时,会继续执行后面的case语句,直到遇到break结束或执行完switch语句结束。
问题7:定义和声明?(已解决)
描述:
-
什么是定义?什么是声明?两者的区别。
答:
- 定义:是编译器创建了一个变量或者是对象,并且为该变量(对象)申请了空间;该空间与变量(对象)进行了绑定,同时生成和消亡。且只能定义一次,多次定义编译器会提示重复定义。
- 声明:仅仅是创建了一个变量或者是对象,并没有为他赋予内存空间。但其他代码不能再使用已经声明的名字,且再使用声明的名字时,再申请内存空间。如图书馆占座
- 区别:定义已经为变量(对象)申请了内存空间,而声明没有。
问题8:register内存地址?(已解决)
描述:
-
当使用&符号取register定义变量的地址时错误?
**答:**register定义的变量时保存再CPU中,不可能放在内存中,所以使用&符号得不到该变量的地址。
问题9:使用strlen求char数组长度?(已解决)
描述:
int main(int argc, char *argv[])
{
char ch1[2],ch2[6],ch3[100];
printf("%d,%d,%d\n",strlen(ch1),strlen(ch2),strlen(ch3)); // 输出0,0,0
printf("%d,%d,%d\n",sizeof(ch1),sizeof(ch2),sizeof(ch3)); // 输出2,6,100
return 0;
}
int main(int argc, char *argv[])
{
char ch0[1000],ch1[2],ch2[6],ch3[100];
printf("%d,%d,%d,%d\n",strlen(ch0),strlen(ch1),strlen(ch2),strlen(ch3));// 输出6,4,2,6
printf("%d,%d,%d,%d\n",sizeof(ch0),sizeof(ch1),sizeof(ch2),sizeof(ch3)); // 输出1000,2,6,100
return 0;
}
-
已知两个代码段,为什么两次字符串定义的长度相同,输出字符串长度不同?
**答:**sizeof()关键字和strlen()函数计算字符串长度时,sizeof()与字符串初始化无关,而strlen()与字符串的初始化有关。若不初始化,输出的结果未知,因为strlen()计算字符串到’\0’的字符个数。
问题10:结构体内存大小?(已解决)
描述:
struct Name
{
char ch;
int num;
long l;
};
int main(int argc, char *argv[])
{
struct Name name;
printf("%d\n",sizeof(name));//输出16
return 0;
}
-
为什么结构体的大小输出为16?
**答:**结构体的内存大小为补全原则,即按照结构体中最大的数据类型创建矩形内存,其他较小的数据则补全到可以放的内存中。该代码块最大类型是long(8个字节),较小的数据类型有char(1个字节)、int(4个字节)。如图:
ch | num | num | num | num | |||
---|---|---|---|---|---|---|---|
l | l | l | l | l | l | l | l |
所以该结构体的内存大小为2*8=16。建议参考链接学习
问题11:volatile的含义用法?
问题12:初始化?
int main(int argc, char *argv[])
{
int a,i = 1,n;
//scanf("%d",&n);
while(i <= 4)//while(i <= n)//当使用键盘输入n时,a初始化为随机数。常量为4时,a初始化为0?
{
a *= i++;
}
printf("%d\n",a);
return 0;
}
问题13:static关键字修饰的内容与普通内容的区别?(已解决)
描述:
-
static修饰的局部变量、全局变量、函数与普通局部变量、普通全局变量、普通函数有什么区别
答:
-
局部变量:static修饰的局部变量只被初始化一次,下次使用时的数据为上次的值。
-
全局变量:static修饰的全局变量只被初始化一次,防止其他文件的引用,作用域仅为该模块中。
PS:static修饰的全局变量可以存在在多个.c文件引用的.h头文件中,但只能被赋值一次。
-
函数:static修饰的函数只有一份,而普通函数再调用时则是对函数进行拷贝。
-
问题14:指针变量?(已解决)
描述:
-
当定义一个指针时,各个符号代表的意思?如代码块:
int i = 10; int *p = &i; *p = NULL;
答:
- "*"代表钥匙,开启指针的钥匙;
- "p"代表指针指向的地址;
- "*p"代表使用钥匙开启p指针,访问指针指向的地址,即取得指针指向的地址的数据。
- 此处代码将i的地址赋值给了指针p,即p保存的是i的地址;当*p发生改变时,即指针p指向的地址保存的数据发生了改变,i也发生改变。
-
PS: int *p = &i; ==> int *p; p = &i; !=> int *p; *p = &i; 即:p的数据类型是int *,而非int。当使用sizeof关键字求空间时,i为4个字节,p为8个字节。
问题15:数组在内存中保存如何知道长度?
描述:
- 已知数组名代表首地址或第一个元素的地址,那内存是如何知道该数组有多长?有多少数据的?
问题16:二维数组和指针数据访问?(已解决)
描述:
-
已知C中二维数组的数据在地址中都是连续的,当使用指针加偏移量访问数据时出现问题?如代码块
int main(int argc, char *argv[]) { int a[3][3] = {1,2,3,4,5,6,7,8,9}; int *p = a; printf("%d,%p\n",a[2][1],&a[2][1]);//8,0x7ffd23477bfc printf("%d,%p\n",*(p + 2 * 3 + 1),(p + 2 * 3 + 1));//8,0x7ffd23477bfc printf("%d,%p\n",*(a + 2 * 3 + 1),&(*(a + 2 * 3 + 1)));//591887412,0x7ffd23477c34 return 0; }
为什么需要用指针才能访问二维数组连续地址的数据,直接使用数组加偏移量不行?
**答:**当使用数组加偏移量访问数据时,如代码*(*a + 2 * 3 + 1),才正确。
问题17:全局变量和静态全局变量?(已解决)
描述:
-
全局变量和静态全局变量异同?
答:
- 同:
- 全局变量和静态全局变量都是存储在静态区,都是以静态存储方式;
- 作用域都包括整个源文件。
- 异:
- 对于有多个源文件构成的源程序,全局变量在所有源文件中都能使用;而静态全局变量只能在定义了该变量的源文件中使用;
- 即全局变量的作用域是源程序,而静态全局变量的作用域是源文件。
- 同:
问题18:typedef对复杂数据类型?(已解决)
描述:
-
当使用typedef对复杂数据类型起别名时注意项?如代码
typedef int (*p)[4];
**答:**注意如代码int *a,的数据类型是int *,而非int。typdef修饰的同理,该代码块中数据类型为int类型的数组指针(int *[4]),标识符名为p。即将(int *[4])数据类型起了一个别名p。