1、指针不能用浮点数之类常量赋值
char *p = “abcdefg”; //对字符串常量:在定义时同时赋给指针一个字符串常量进行初始化,会分配指针空间
float *pip = 3.14; / *错误无法通过编译,不能指望为浮点数之类的常量分配空间 * /
2、数组的形式 i[a] 和 a[i] 的关系是一样的
#include <stdio.h>
int main()
{
/* 我的第一个 C 程序 */
printf("Hello, World! \n");
int a[6];
for(int i = 0; i < 6; i++)
{
i[a] = i;
printf("%d ",i[a]);
}
int b = 2[a];
printf("\n%d",b);
return 0;
}
正确通过编译,在表达上中,指针和数组是可以互换的,因为他们在编译器里的最终形式都是指针,并且可以取下标操作。就像加法一样,取下标操作符的操作数都是可以交换的(它们不在意操作数的先后顺序,就像在加法中3+5和5+3并没有什么不一样)。这就是为什么在一个a[10]的声明中下面两种形式都是正确的:
a[6] = …;
6[a] = …;
3、数组实参的有效操作
①
#include <stdio.h>
int array[100], array2[100];
int main()
{
printf("测试程序\n");
array[1] = 3;
*array = 3;
array = array2;
printf("%d , %d",array[1],*array);
return 0;
}
错误信息:
main.c: In function ‘main’:
main.c:10:8: error: assignment to expression with array type
10 | array = array2;
| ^
解释:上述语句array = array2;将引起一个编译时错误,错误信息是“无法修改数组名”。但是,arr = array2 却是合法的,因为arr虽然声明为一个数组但实际上却是一个指针。
②
#include <stdio.h>
int array[100], array2[100];
void fun1(int *ptr)
{
ptr[1] = 3;
*ptr = 3;
printf("%d , %d\n",ptr[1],*ptr);
ptr = array2;
printf("%d , %d",ptr[1],*ptr);
}
int main()
{
printf("测试程序\n");
fun1(&array[0]);
return 0;
}
③
#include <stdio.h>
int array[100], array2[100];
void fun1(int ptr[])
{
ptr[1] = 3;
*ptr = 3;
printf("%d , %d\n",ptr[1],*ptr);
ptr = array2;
printf("%d , %d",ptr[1],*ptr);
}
int main()
{
printf("测试程序\n");
fun1(&array[0]);
return 0;
}
4、怎样才能检测到链表中存在循环
这个问题看上去比较简单,“怎样才能检测到链表中存在循环?”但提问者不断对问题施加一些额外的限制,使这个问题很快就变得面目狰狞。
通常第一种答案:
对访问过的每个元素作个标记,继续遍历这个链表,如果遇到某个已经做过标记的元素,说明链表存在循环。
第二个限制:
这个链表位于只读内存区域,无法在元素上作标记。
通常第二种答案:
当访问每个元素时,把它存储在一个数组中。检查每一个后继的元素,看看它是否已经存在于数组中。有时候,一些可怜的程序员会纠缠于如何用散列表来优化数组访问的细节之中,结果在这一关卡了壳。
第三个限制:
噢!内存空间非常有限,无法创建一个足够长度的数组。然而,可以假定如果链表中存在循环,它出现在前N个元素之中。
**通常第三种答案(**如果这位程序员能够到达这一步):
设置一个指针,指向链表的头部。在接下去对直到第N个元素的访问中,把N-1个元素依次同指针指间的元素进行比较。然后指针移向第二个元素,把它与后面 N-2 个元素进行比较。根据这个方法依次进行比较,如果出现比较相等的情况就说明前 N个元素中存在循环,否则如果所有N个元素两两之间进行比较都不相等,说明链表中不存在循环。
第四个限制: 噢!不!链表的长度是任意的,而且循环可能出现在任何位置。(即使是优秀的候选者也会在这十关碰壁)
最后的答案:
首先,排除一种特殊的情况,就是3个元素的链表中第2个元素的后面是第1个元素。设置两个指针 pl和 p2,pl指向第个元素。p2指向第三个元素,看看它们是否相等。如果相等就属于上述这种特殊情况。如果不等,把pl向后移一个元素,p2向后移两个元素。检查两个指针的值,如果相等,说明链表中存在循环。如果不相等,继续按照前述方法进行。如果出现两个指针都是NULL的情况,说明链表中不存在循环。如果链表中存在循环,用这种方法肯定能够检测出来,因为其中一个指针肯定能够追上另一个(两个指针具有相同的值),尽管有可能要对这个链表经过几次便力才能检测出来。
这个问题还有其他一些答案,但是上面所说的几个是最常见的。
5、在关系表达式中负数和无符号整数比较时自动升级为正数
例子:
结论:
因为sizeof返回的数是无符号整形
然后-1和无符号数比较后自动升级为无符号数了
然后就变成一个好大的数了
6、指针符号和多行注释冲突
后果:
7、指针打印字符串
#include <stdio.h>
int main()
{
char *receiveData = NULL;
receiveData = "ABCDEFG";
printf("%c \n",*receiveData);
printf("%s \n",receiveData);
printf("%s \n",&(*receiveData));
printf("%x",&receiveData);
return 0;
}
输出:
解释:receiveData 保存的是字符串的首地址,类似于数组。
%x 是以十六进制形式打印
注意 %s 的用法,%s 的对象是地址
总结:在c语言中存储一个字符串,一般有两种方法,一种是字符指针,一种是使用字符数组。比如:
const char *str = "hello";
const char str[] = "hello";
C语言百分号加字母%d%p%o%x%u%c%s%f%e%g代表作用
%d整型输出,%ld长整型输出,
%p指针变量地址,如果数处数据不够8位数,则左边补零
%o以八进制数形式输出整数,
%x以十六进制数形式输出整数,
%u以十进制数输出unsigned型数据(无符号数)。
%c用来输出一个字符,
%s用来输出一个字符串,
%f用来输出实数,以小数形式输出,
%e以指数形式输出实数,
%g根据大小自动选f格式或e格式,且不输出无意义的零。