Pointer_6
程序员文章站
2022-06-23 13:40:35
...
#include <stdio.h>
#include <string.h>
struct myStruct
{
int a;
int b;
int c;
};
int func(char* str)
{
// 统计字符串中各个字符的ASCII码值之和
int num = 0;
int len = strlen(str);
for(int i = 0; i < len; i++)
{
num += *str;
str++;
}
return num;
}
void func_1(char* s)
{
char c;
c = *(s + 3);
*(s + 3) = *(s + 0);
*(s + 0) = c;
c = *(s + 1);
*(s + 1) = *(s + 2);
*(s + 2) = c;
}
int main()
{
struct myStruct ss = {2, 3, 4};
struct myStruct *ptrStruct = &ss;
int *p = (int*)ptrStruct;
// 通过ptrStruct访问ss的三个成员变量
printf("%d\n", ptrStruct->a);
printf("%d\n", ptrStruct->b);
printf("%d\n", ptrStruct->c);
printf("\n");
// 通过p来访问ss的三个成员变量,这样访问变量是不正规的
printf("%d\n", *p);
printf("%d\n", *(p + 1));
printf("%d\n", *(p + 2));
// 所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存
// 放在连续的存储区里,单元和单元之间没有空隙。但在存放结构对象的
// 各个成员时,在某种编译环境下,可能会需要字对齐或双字对齐或者是
// 别的什么对齐,需要在相邻两个成员之间加若干个"填充字节",这就导
// 致各个成员之间可能会有若干个字节的空隙。
// 即使*p访问到了结构对象ss 的第一个成员变量a,也不能保证*(p+1)
// 就一定能访问到结构成员b。因为成员a 和成员b 之间可能会有若干填充字节,
// 说不定*(p+1)就正好访问到了这些填充字节呢。这也证明了指针的灵活性。
// 要是你的目的就是想看看各个结构成员之间到底有没有填充字节,
// 嘿,这倒是个不错的方法。不过指针访问结构成员的正确方法应该是使用指针ptr
char sz[20] = "test";
printf("%d\n", func(sz));
printf("\n");
int n1 = 125;
printf("%d\n", n1);
func_1((char*)&n1);
printf("%d\n", n1);
printf("\n");
// 注意这是一个32 位程序,故int 类型占了四个字节,char 类型占一个字节。
// 函数func_1的作用是把一个整数的四个字节的顺序来个颠倒。注意到了吗?
// 在函数调用语句中,实参&n1的结果是一个指针,它的类型是int *,
// 它指向的类型是int。形参这个指针的类型是char *,它指向的类型是char。
// 这样,在实参和形参的结合过程中,我们必须进行一次从int *类型到
// char *类型的转换。
// 我们可以这样来想象编译器进行转换的过程:编译器先构造一个临时指针char *temp,
// 然后执行temp=(char *)&n1,最后再把temp 的值传递给s。所以最后的结果是:
// s的类型是char *,它指向的类型是char,它指向的地址就是n1的首地址。
unsigned int n2 = 20345686;
unsigned int *pn2 = (unsigned int *)n2; // 将一个无符号整数值转换为一个指针
// 间接引用n2时,会出现内存访问错误,但可以将地址输出
//printf("%d\n", *pn2);
printf("0x%p\n", pn2);
printf("\n");
pn2 = &n2;
// 将一个无符号指针转换为无符号整数
unsigned int n3 = (unsigned int)pn2;
printf("%d\n", n3);
printf("0x%p\n", n3);
// getchar()是一个缓冲函数,结束时,必须输入一个回车,getchar()函数才从
// 键盘缓冲区中读取字符
getchar();
return 0;
}
上一篇: 大事和小事
下一篇: 此文章正在审核中,即将跳转到首页。。。
推荐阅读