一、指针基础:
指针本质上也是一个变量,需要占用一定的内存空间,用于保存内存地址的值,可以通过指针修改内存中的任意地址内容
常量与指针:
const int* p; //p可变,p指向的内容不可变
int const* p; //p可变,p指向的内容不可变
int* const p; //p不可变,p指向的内容可变
const int* const p; //p和p指向的内容都不可变
口诀:左数右指。当const出现在*号左边时指针指向的数据为常量当const出现在*后右边时指针本身为常量
二:数组基础:数组是相同类型的变量的有序集合。
数组地址与数组名
数组名代表数组首元素的地址
数组的地址需要用取地址符&才能得到
数组首元素的地址值与数组的地址值相同
数组首元素的地址与数组的地址是两个不同的概念
在表达式中数组名只能作为左值使用
数组名的盲点
数组名可以看做一个常量指针,数组名其实并不是指针,在外部声明时不能混淆
数组名“指向”的是内存中数组首元素的起始位置
在表达式中数组名只能作为右值使用
只有在下列场合中数组名不能看做常量指针
数组名作为sizeof操作符的参数
数组名作为&运算符的参数
三:数组与指针:
指针是一种特殊的变量,与整数的运算规则为p + n等价于 (unsigned int)p + n*sizeof(*p);
指针之间只支持减法运算,且必须参与运算的指针类型必须相同:
只有当两个指针指向同一个数组中的元素时,指针相减才有意义,其意义为指针所指元素的下标差
当两个指针指向的元素不在同一个数组中时,结果未定义
指针也可以进行关系运算:< <= > >=,前提是两个指针必须指向同一个数组的元素,任意两个指针之间的比较运
算 (==, !=)无限制;
从理论上而言,当指针以固定增量在数组中移动时,其效率高于下标产生的代码;
a和&a的区别:
a为数组是数组首元素的地址
&a为整个数组的地址
a和&a的意义不同其区别在于指针运算
a + 1 (unsigned int)a + sizeof(*a)
&a + 1 (unsigned int)(&a) + sizeof(*&a)(sizeof(a))
Motorola面试题:
int a[5] = {1, 2, 3, 4, 5};
int* p1 = (int*)(&a + 1);
int* p2 = (int*)((int)a + 1);
int* p3 = (int*)(a + 1);
printf("%d, %d, %d\n", p1[-1], p2[0], p3[1]);
输出:5 0x000000 3
数组参数:C语言中,数组作为函数参数时,编译器将其编译成对应的指针
void f(int a[]); void f(int* a);
void f(int a[5]); void f(int* a);
一般情况下,当定义的函数中有数组参数时,需要定义另一个参数来标示数组的大小
指针和数组的对比:
数组声明时编译器自动分配一片连续内存空间
指针声明时只分配了用于容纳指针的4字节空间
在作为函数参数时,数组参数和指针参数等价
数组名在多数情况可以看做常量指针,其值不能改变
指针的本质是变量,保存的值被看做内存中的地址
四:C语言中的字符串
从概念上讲,C语言中没有字符串数据类型,使用字符数组来模拟字符串,以’\0’结束的字符数组,语言中的字符串可以分配于栈空间,堆空间或者只读存储区 例char s=“hello”
字符串长度:C语言中的字符串长度指的是第一个’\0’字符前出现的字符个数
strlen的返回值是用无符号数定义的
字符串复制:
char* strcpy(char* dst, const char* src);
字符串连接:
char* strcat(char* dst, const char* src);
字符串比较:
int strcmp(const char* s1, const char* s2);
strcmp以0值表示两个字符串相等
第一个字符串大于第二个字符串的时候返回值大于0
第一个字符串小于第二个字符串的时候返回值小于0
strncpy只复制len个字符到目标字符串
当源字符串的长度小于len时,剩余的空间以’\0’填充。
当源字符串的长度大于len时,只有len个字符会被复制,且它将不会以’\0’结束。
strncat最多从源字符串中复制len个字符到目标串中
strncat总是在结果字符串后面添加’\0’
strncat不会用’\0’填充目标串中的剩余空间
字符串复制:
char* strcpy(char* dst, const char* src)
{
char* ret = dst;
assert(dst && src);
while( (*dst++ = *src++) != '\0' );
return ret;
}
一句话实现字符串长度计算:
size_t strlen(const char* s)
{
return ( assert(s), (*s ? (strlen(s+1) + 1) : 0) );
}