%#
%#
表示格式化输出,一般这样使用 %#p
。
%x
表示输出 16 进制格式,但是受环境影响,格式会变化。
%p
表示输出 16 进制 系统寻址范围为取值范围的整数。
有多少位就打印多少位。32位系统一般是 8 位,64 位系统一般 16 位。不足 8 位自动补 0 ;
例如 int 4 个字节,那么 %p
打印输出共 32 位 2 进制表示的值,不足位数自动补 0 。主要用来输出地址、指针。
%#
表示格式化输出,16 进制自动加上 0x
。
指针地址的字节数
指针地址都是使用 4 个字节存储。
char *
,int *
,double *
等类型的指针类型,都是四个字节!
(char*)
这个表示将一个值转为 char 类型的指针。
这个表示强制转换,此时不代表特殊的意义。跟 =下列例子意义相同。
char a = '6';
int b = (int)a;
示例
#include <stdio.h>
int main( void )
{
char a = 'a';
int b = (int) &a; /* 将地址作为值赋给b,指针都是用4字节存储 */
printf( b );
char *p;
p = (char *) b; /* 将值转为地址形式 */
printf( *p );
return(0);
}
while({表达式})
C语言中没有布尔类型,https://www.whuanle.cn/archives/738
while 单条件为 true 是或 1 或非0 时,继续运行。碰到 flase、 0 、'\0' 等情况结束。
whille(a>b)
while(i)
while(2)
char *p
与 char* p
两者本质是一样的,都是定义一个指针。但是他们定义多个变量时,会出现差异。
当使用 char*
时,代表声明的都是指针变量,例如:
char* a, b, c;
下面这样,表示只有 j 才是指针变量,其它都是 char 变量。
char *j,p,k;
但是这样不好,普通变量和指针变量一起定义,这样容易出现歧义,应该分开两行声明。
如果实在要放到一起声明的话,一般使用如下的方式定义
char l,m,*n
对于方法来说,* 的位置不重要。
char* test()
char *test()
malloc 和 calloc
两者都是分配内存,在头文件中定义 stdlib.h
。
malloc 在分配内存时,不会对内存进行“初始化”,所有字节的内容仍然是被分配时所含的随机值。
calloc 的话,分配内存时,会对所有字节置零。
在较新的 C 语言规范中,malloc 和 calloc 都返回一个void型的指针,也就是说,返回的地址值可以假设为任何合法的数据类型的指针。
一般来说,我们使用指针,都是要用数据类型去定义的,例如 char *p
、int *i
。
而使用 malloc 和 calloc 的话,可以转成任何类型的指针。
以下是错误的使用,原因在于 malloc 返回的是 void
#include <stdio.h>
#include <stdlib.h>
int main() {
char *p;
p = malloc(200);
gets(p);
printf(p);
free(p);
return 0;
}
所以分配内存,返回指针,应该使用如下的方式接收
p = (char *)malloc(200);
还有一个问题,分配内存,不一定都是成功的,如果分配失败,会返回 NULL。
所以应该这样写
#include <stdio.h>
#include <stdlib.h>
int main() {
char* p;
p = (char*)malloc(200);
if (p == NULL)
{
printf("分配失败");
exit(1);
}
gets(p);
printf(p);
free(p);
return 0;
}
指针的初始化
指针初始化有两种方法,一种是使用已有变量地址,一种使用动态分配内存。
示例
char a = 'a';
// 方法1
char* p = &a;
// 方法2
p = (char*)malloc(200);
指针变量也是变量
指针变量也是变量,也有作用域。
#include <stdio.h>
char* test(char* p) {
printf("p 的地址 %#p \n",&p);
return p;
}
int main() {
char a = 'a';
char* p1 = &a;
printf("p1 的地址 %#p \n",&p1);
char* p2 = test(p1);
printf("p2 的地址 %#p \n", &p2);
return 0;
}
输出结果如下
p1 的地址 000000C166F5FA08
p 的地址 000000C166F5F9C0
p2 的地址 000000C166F5FA28
可以看到每个 p 的地址都不同。指针变量也是,也有作用域。
大端和小端存储
字和字节:
一个字节为 8 位。这个是几乎所有计算机通用的。
以 CPU 的位数为单位,一次所能处理的位数转为字节数,是全字长。另外还有双字长,半字长,
一个 64 位计算机中,全字长是 8 个字节(64) 位。双字长是 16 字节,半字长是 4 字节。
可以这样理解。在 32 位系统中 ,全字长 4 字节, 半字长 2 字节,双字长 8 字节。
short 是 半字长(2字节), long 是全字长(4字节),double 是双字长。
一般一个字节的位,是高位在左,低位在右。多个字节是高字节在左,低字节在右。
在 寄存器 和 内存中,如果 都是高位在左和低位在右,则称为小端存储。一个 long 转为 int ,只有低位的 2/4 个字节被 int 接收。union 中变量共享内存,低位会互相影响。
void指针
就好像 C# 或 java 的 object。
object a = new MyClass();
int b = (MyClass)a.Test();
void 指针可以指向任何类型变量地址。
但是要使用此地址的值,必须先转为对应类型的指针类型。
#include <stdio.h>
int main() {
char a = 'a';
int b = 0;
void* p = &a;
printf("%d", *(char*)p);
p = &b;
printf("\n");
printf("%d", *(int*)p);
}
文章评论