char* const p
p是指针,p本身不可更改,p指向的空间中的变量可以更改。
const char* p
p是指针,p本身可更改,p指向的空间中的变量不可更改。
在char* const p中,const位于p的右侧,表示p本身是一个不可更改的指针。原反补也就是说,p始终指向同一个地址,不允许更改p的指向。但是p指向的地址中的值是可以更改的。
二进制中(原反补)中:
0打头的二进制代表正数
1打头的二进制代表负数
unsigned char a=200;
unsigned char的范围是:0~255
因为是将整数存储到char类型中,所以存储时发生截断。
unsigned char b=100;
unsigned char c=0;
c=a+b
数字才能进行+的运算
所以a+b操作之前,要先将a和b进行整型提升,再想加。
计算完的结果的原码,存储到c中。
c是char类型,所以截断后存入。
printf(“%d %d”,a+b,c);
a+b:
%d的意思是:将它的结果的补码,按照有符号整型打印出来。
c:
%d的意思是:将它按照有符号整型打印出来。但是c是char类型,所以首先将c整型提升,再按照有符号整型打印出来。
unsigned int a=0x1234
unsigned char b= *(unsigned char *)&a
问题:在32位大端模式的处理器上,b等于多少?(正确答案:A)
A . 0x00
B . 0x12
C . 0x34
D . 0x1234
首先,32位机器中大端存储数据是先低地址再高地址。
(unsigned char *)&a
将a的地址强转为char * 类型,代表着在解引用a时,解出来的空间是一个字节,解出来的是00。
所以b是0x00。
5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果:
A选手说:B第二,我第三;
B选手说:我第二,E第四;
C选手说:我第一,D第二;
D选手说:C最后,我第三;
E选手说:我第四,A第一;
比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。
#include<stdio.h>
void game()
{
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
for (int a = 1; a <= 5; a++)
{
for (int b = 1; b <= 5; b++)
{
for (int c = 1; c <= 5; c++)
{
for (int d = 1; d <= 5; d++)
{
for (int e = 1; e <= 5; e++)
{
if (
((b == 2) + (a == 3) == 1) &&
((b == 2) + (e == 4) == 1) &&
((c == 1) + (d == 2) == 1) &&
((c == 5) + (b == 3) == 1) &&
((e == 4) + (a == 1) == 1)
)
{
if ((a*b*c*d*e) == 120)
{
printf("%d %d %d %d %d", a, b, c, d, e);
}
}
}
}
}
}
}
}
int main()
{
game();
return 0;
}
烧香问题
两根香,它们不均匀。每根香烧完都是刚好能1小时烧完。(现在没有计时器)
要求:通过烧香,确定一个15分钟的时间段。
解题思路:
1.两根香,一根两头烧,一根一头烧;
第一根香烧完就是半小时
第一根香烧完时,第二根香只烧了一半,剩下的香刚好可以烧30分钟。
接下来把第二根香的另一头也点燃,现在是剩下的香两头烧。
剩下的香,在两头烧的情况下,可以烧15分钟。
malloc(40)
向内存申请40个字节的空间
malloc返回一个东西——申请的空间的首地址
int * p = (int*)malloc(40)
free(p)
将申请的空间地址存到指针p中(在存放前需要强制类型转换)
free(p)的意思是将p指向的内存释放。但不会将p置为空
char * p = “hello bit”;
p中放不下hello bit\0。
p中放的是 h 的地址。
传址和传值
这两个在使用时:
传址:直接操作空间内容
传值:操作传入的值
函数strlen()
C语言中strlen是一种函数,主要用于计算字符串的长度(字符元素个数)。
strlen()从字符串的开头位置依次往后面计数,直到遇到‘\0’停止,所计算的字符串大小为‘\0’以前的字符所计算的值,最终的字符串长度不包括‘\0’
strlen()是一个函数,因此调用这个函数需要引用的头文件是<string.h>,它的原型是size_t strlen(const char* str);str表示的是需要计算长度的字符串,由此看出传参的时候应该传的是一个地址而不是一个数值。
strcmp(arr1,arr2)
用于比较两个字符串并根据比较结果返回整数。基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。
assert(arr)
断言,检查指针是否合法。
使用断言的时候需要引用头文件assert.h.
追加字符串
使用strncat(arr1,arr2,a)
在arr1后面追加arr2,追加a个arr2。
是否为子集
库函数strstr(arr1,arr2)
arr2是否为arr1的子集。
字符串,知道第一个地址,就可以往后打印了。
ret是一个地址,
printf("%s",ret);//ret是指针,这句代码可以打印出字符串。
关于代码:
printf("%d",sizeof('a'));
C语言结果是:4
C++结果是:1
int a[4]={1,2,3,4};
a代表的是数组指针,首元素地址。
a代表的是首元素地址。
a[ 0 ]也代表的是首元素地址。
a[ 0 ] <=> * ( a+0 ) = a(首元素向后0个步长,然后解析出的元素元素)
a [ 3 ] <=> * ( a+3 ) = 第四个元素地址(首元素向后三个步长,然后解析出的元素)
由此推出:
a [ -1 ] <=> * ( a+(-1) )
此时指的a的位置向后 - 1 个步长,解析出的地址。
(结论是正确的)
逗号表达式 (举例一看就会)
逗号表达式 (0, 2) 的结果是 2。
该逗号表达式中,左边的表达式是 0,右边的表达式是 2。根据逗号表达式的运算法则,会先计算左边的表达式,然后计算右边的表达式,并返回右边表达式的值作为整个逗号表达式的结果。
因此,计算过程如下:
1. 首先计算左边的表达式 0,其结果为 0。
2. 接着计算右边的表达式 2,其结果为 2。
3. 最后,整个逗号表达式的结果是右边表达式的结果,即 2。所以,逗号表达式 (0, 2) 的结果是 2。
复习知识点:
sizeof(数组名)、&数组名
这两种中的数组名都代表整个数组。
除此之外的 “ 数组名 ” 都代表的是数组首元素地址。
int main()
{
char *c[] = {"ENTER","NEW","POINT","FIRST"};
char**cp[] = {c+3,c+2,c+1,c};
char***cpp = cp;
printf("%s\n", **++cpp);
printf("%s\n", *--*++cpp+3);
printf("%s\n", *cpp[-2]+3);
printf("%s\n", cpp[-1][-1]+1);
return 0;
}
printf("%s\n", **++cpp);
这一句代码,先给cpp++,再解引用找到cp[ 1 ],再解引用。
最终得到POINT
printf("%s\n", *--*++cpp+3);
cpp先++,再解引用,再 - - ,再解引用,再+3。
最终结果是ER
printf("%s\n", *cpp[-2]+3);
结果是:ST
printf("%s\n", cpp[-1][-1]+1);
刚开始CPP是指向首元素,但是前面三句过后,xpp指向的位置是c+1的地址。
结果是:EW
断言
想要同时断言两个指针,只需&&
int * aa;
int * bb;
assert (aa&&bb);
关于NULL:
在不同的编程语言中,null的值可以是不同的。以下是一些常见编程语言中null的值:
- 在Java中,null的值为null。
- 在JavaScript中,null的值也是null。
- 在C和C++中,null的值为0或者NULL(通常通过宏定义为0)。
- 在Python中,null的值为None。
需要注意的是,虽然null在不同的编程语言中可能有不同的值,但它们都表示相同的含义:为空值或没有指向对象。