若不用free()释放,容易造成内存泄露(即内存被浪费、耗尽)。
const关键字修饰的的变量无法修改,但存放的位置取决于变量本身是全局变量还是局部变量。当修饰的变量是全局变量,则放在全局区,否则依然在栈区分配。
static关键字修饰的变量存在全局区的静态变量区。
常变量与宏定义的概念不同。代码区
常变量存储在静态存储区,初始化后无法修改。
宏定义在预处理阶段就被替换。不存在与任何内存区域。
格式控制符 %s 跟随一个地址,并当做是字符串第一个元素对应的地址.char *s = "Hello"
从该首地址开始解析,直到 '\0' 结束。
在这里指的是 s[0] = 'H' 的地址。
对于打印结果的一些解释:char *s[10] = {"Hello", "World"}
· 对二维数组进行操作与输出
· 二维数组传参
- s 等价于&s[0],是指向[存储"Lee"的一维数组]的指针
- s+1等价于&s[1],是指向[存储"Zero"的一维数组]的指针
- *s+1等价于(*s)+1,s通过*解析首先得到[一维数组"Lee"]
即指向[一维数组"Lee"的第一个元素'L'的地址]的指针s[0];
对该指针+1,相当于s[0]+1,使得指针指向[一维数组"Lee"第二个元素'e'的地址]
格式控制符%s将该元素看成字符串的首地址,因而打印出"ee"
二维数组主要有两种传参方式(以下两种是函数声明的方式。声明函数后,都是使实参为数组名来调用函数:f(s);)
- void f(char (*s)[10]) {} —— 一维数组指针作形参
二维数组名实际上就是指向一维数组的指针。因此这里形参s是个指向行元素的指针,与二维数组名匹配。
- void f(char s[][10]) {} —— 二维数组指针作形参
对于这种方法,仅二维数组的数组列数可以省略,不可省略行数。f(char s[][])是错误的。
也就是说,1.和2.方式中都需要正确指定行数。
- f(char **s),f(char *s[])的方式声明函数虽然能编译输出,但编译器可能会出现以下警告信息:
P.S. 当然,如果一定要用二维指针作实参f(char **s),在传参的时候可以将s强制转化:f((char **)s),函数内部操作元素可以通过*((int *)a+i*10+j)的方式……但何必呢。复制代码
- [Warning] passing argument 1 of 'f' from incompatible pointer type
- [Note] expected 'char **' but argument is of type 'char (*)[10]'
如果一定要试试,这里也有个例子:复制代码
- #include <stdio.h>
- void f(char **s) { //形参s是个二维指针
- printf("%c\n", *((char *)s)); //输出:L
- printf("%s\n", ((char *)s)); //输出:Lee
- printf("%c\n", *((char *)s+10)); //输出:H
- printf("%s\n", ((char *)s+10)); //输出:Hero
- }
- int main() {
- char s[10][10] = {"Lee","Hero"};
- f((char **)s); //“我一定要把s看做二维指针去传参!”
- return 0;
- }
解释:
数组名作为函数参数传递时,会退化成指向数组首元素的指针。
当把s作为参数传递给f()函数时,实际上是把指针数组的首地址传递给了f()函数。这样,f()函数中的s就是一个二级指针,它指向了指针数组的第一个元素,也就是第一个字符串的地址。
f()函数接受一个二级指针作为参数。由此,f()函数中的s[0]和s[0][0]与主函数中的s[0]和s[0][0]含义相同。
优先级:() \(>\) ++ \(>\) 指针运算符* \(>\) +[table][tr]二级指针
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) | Powered by Discuz! X3.4 |