只有十进制有正负.
常量在数据段,动态内存分配在堆,变量在栈
-----------------------------------
计算二维数组的长度
行数 row = sizeof(arr) / sizeof(arr[0]); sizeof(arr[0] 是第一行的长度
列数 col = sizeof(arr[0]) / sizeof(arr[0][0]);
二维数组作为函数参数传递是,行数无意义,不需要传,但列数一定要传,写上去,行数可以再作为一个参数传递. int func( int arr[][col],int row);通过sizeof(arr[0])可以计算出列的字节数 ,arr[][col]传递的只是一个地址,首地址,长度为4.
刷新输出缓冲区fflush(stdout);printf只有到缓冲区满,或者遇到回车才输出
如:
{
printf("abc");
while(1);
}
是不会输出abc的.若在c后加回车\n,则会输出.
关闭行缓冲区 stty -echo-icanon ,打开是把减号都省去stty echo icanon
------------------------------------
gets(str)接收字符串,getchar()接收一个字符
------------------------------------
定义指针int *p时,与定义普通变量int a,一样,在栈中都分配内存,只是对a而言,栈中存的是a的值,一个可变的值.然而对*p而言,栈中存的是p所指向的地址值.
0地址(NULL)不能进行操作
指针变量的加减是指该指针按单位进行运算(单位由指针类型定).intarr[4];刚 int *p = arr.则 (p+1) -arr = 1;而不是4(BYTE)
指针类型表示以指针为基址,偏移的字节数,
--------------------------------------
char *str = "abcdefg"; 定义字符串常量,里边的内容不可改,如 *str ='A',是不能把a替换成A 的
二维数组arr[row][col]中 *(arr + n) 表示取第n - 1行的首地址.而*(*arr + n) + 0) 表示取第n - 1行首元素值(二维数组是二级指针)
const int *p(等同于intconst *p); 定义不能通过P来修改p指向的地址的内容.但该地址的可以通过定义该地址的变量来修改.如int b; p = &b; *p = 1;不允许.但b = 1 是允许.
int * const p;指p所指向的地址不能改,但内容可以改
const int * const p;则指针p只读;
---------------------------------------
char str = "abcd";这是不对的,str是字符类型,而"abcd"是一个字符串,类型不同,也不匹配.但 char *str ="abcd";是对的str是指向char型的地址,而字符串的首元素(地址)就是char 类型.
---------------------------------------
二维数组arr[3][4],arr+1指向的是第二行首地址,而arr[0]+1,是第一行第二个元素地址.
--------------------------------------
int *p[3] 这是一个指针数组,里边的每个元素都是指针.
int (*p)[3] 这是一个指向二级数组的指针.arr[3][4]; p = arr;则 *(p+1)表示第二行的首地址,*(*(p+1)+1)表示第二行第二个元素.
--------------------------------------
指针数组 int *p[3],指针的数组,
数组指针 int (*p)[3],数组的指针,定义了一个数组,数组元素存放的地地址,即二级指针.p指向数组的首地址. arr[3][2];p = arr;则在内存中的指向为
p -> p[0] --> arr[0]
p[1] --> arr[1]
p[2] --> arr[2]
因此 p+1 指向p[1], 取值 *(p+1)则p[1]的值,还是一个地址,这个地址指向arr[1]的首地址,再取值*(*(p+1))才是arr[1][0]值.
二维数组 arr[3][4] 的数组名 arr 与取地址 &arr是同一个地址.arr是二级指针,而arr[0]是一级指针,但是 arr,arr[0]都是指向数组的首地址.因此**arr = *arr[0] = arr[0][0];
arr,&arr, arr[0], &arr[0]是同一个数.
----------------------------------------
-------------------------------------------
函数的存在代码段里,只是运行是会在栈里运行.函数名指向的地址是函数在栈的地址,在栈的地址无法获取.
------------------------------------------
malloc动态内存分配是分配连续的堆地址,若堆中没有连续的足够大的空间,则返回NULL.
malloc 至少分配16个字节,而且分配的空间是16的整数倍
----------------------------------------
free()函数是把内存块释放,但指向该内存块的指针p并没有删除,还是指针这个内存(指向的地址没变);因此释放后让p = NULL;
---------------------------------------
栈里的地址函数执行结束后会释放,所以栈里的地址不能作为返回值,但堆里的地址需要手动释放,所以从子函数返回地址给调用函数,返回地的地址应该是通过内存分配得到的地址.
---------------------------------------
void func(int *p)
{
p = (int *)malloc(sizeof(int));
}
void main(void)
{
int *s =NULL;
func(s);
*s = 10;
}
上边的main函数调用func函数,但是指针s指向的地址并不是p所指向的地址,也就是说s并没有指向内存分配得到的地址.因为在传参时
s = NULL:
p = NULL;
func(s),只是将s的值(NULL)赋给p,因此p先指向s的值,再指向内存分配得到的首地址.而s和p是两个不同的地址,所以p的值(即p指向的地址)与s的值是两个不同的数,自然s指向的地址不会是分配得到的地址.若要得到分配的地址,可以通过二级指针实现修改如下:
void func(int **p)
{
*p = (int *)malloc(sizeof(int));
}
void main(void)
{
int *s =NULL;
func(&s);
*s = 10;
}