编程语言
首页 > 编程语言> > C语言指针基础编程练习1(指针、地址、基本指针运算、各基本类型数组、一维指针数组、函数传参、数组传址、sizeof的使用注意)

C语言指针基础编程练习1(指针、地址、基本指针运算、各基本类型数组、一维指针数组、函数传参、数组传址、sizeof的使用注意)

作者:互联网

运行结果截图(代码在截图下面):

 

 

 

 

 

 

 

 

 

 代码:

#include <stdio.h>
// 不要在include头文件的语句末加分号
#include <string.h>

int getSizeOfDataType(char * dataType)
{
printf("\ngetSizeofDataType() loading...\n");

int size;
if ("char" == dataType)
{
size = sizeof(char);
printf("sizeof(char):%d\n", size);
}else if ("int"== dataType)
{
size = sizeof(int);
printf("sizeof(int):%d\n", size);
}else if ("short" == dataType) {
size = sizeof(short);
printf("sizeof(short):%d\n", size);
}else if ("long" == dataType) {
size = sizeof(long);
printf("sizeof(long):%d\n", size);
}else if ("long long int" == dataType)
{
size = sizeof(long long int);
printf("sizeof(long long int):%d\n", size);
}else if ("float" == dataType) {
size = sizeof(float);
printf("sizeof(float):%d\n", size);
}else if ("double" == dataType) {
size = sizeof(double);
printf("sizeof(double):%d\n", size);
}else if ("int *" == dataType)
{
size = sizeof(int *);
printf("sizeof(int *):%d\n", size);
}else if ("char *" == dataType)
{
size = sizeof(int *);
printf("sizeof(char *):%d\n", size);
}else
{
size = 0;
printf("!!!Unknown datatype, please contact IT support team in your company for further fix...\n");
}

int getAddressSize = 0;
printf("sizeof(internalStorageAddressSize):%d\n",sizeof(&getAddressSize));

printf("getSizeofDataType() finished...\n\n");

return size;
}

void printCharPointArray( char * arrayName, char * * arr, int length)
{
// 如果在函数内用sizeof来获得数组长度,会发现数组退化成了指针,获得的只是指针的长度,因此要在函数外计算出数组长度再传进函数里
printf("\nprintCharPointerArray() loading...\n");
// 打印指针数组元素
printf("(char *) array length is: %d\n",length);
printf("字符串型指针数组有%d个元素\n",length);
printf("打印指针数组%s:\n", arrayName);
for(int i = 0; i < length; i++)
{
printf("指针数组第%d个元素是%p,", i, arr[i]);
printf("以指针数组第%d个元素为地址所存储的值是: %s\n", i, arr[i]);
}

printf("printCharPointerArray() finished...\n\n");
}

void printIntPointerArray( char * arrayName, int * * arr, int length)
{
// 如果在函数内用sizeof来获得数组长度,会发现数组退化成了指针,获得的只是指针的长度,因此要在函数外计算出数组长度再传进函数里
printf("\nprintIntPointerArray() loading...\n");
// 打印指针数组元素
printf("(int *) array length is: %d\n",length);
printf("整型指针数组有%d个元素\n",length);
printf("打印指针数组%s:\n", arrayName);
for(int i = 0; i < length; i++)
{
printf("指针数组第%d个元素是%p,", i, arr[i]);
printf("以指针数组第%d个元素为地址所存储的值是 %d\n", i, *arr[i]);
}

printf("printIntPointerArray() finished...\n\n");
}

void printCharArray( char * arrayName, char * arr, int length)
{
// 如果在函数内用sizeof来获得数组长度,会发现数组退化成了指针,获得的只是指针的长度
printf("\nprintCharArray() loading...\n");

printf("Char array length is: %d\n",length);
printf("字符串型数组有%d个元素\n",length);
//打印字符串数组元素
printf("打印字符串数组:%s\n", arrayName);
printf("打印字符串数组:%s\n", arr);


printf("printCharArray() finished...\n");
}

void printIntArray(char * arrayName, int * arr, int length)
{
// 如果在函数内用sizeof来获得数组长度,会发现数组退化成了指针,获得的只是指针的长度
printf("\nprintIntArray() loading...\n");

printf("Int array length is: %d\n",length);
printf("整型数组有%d个元素\n",length);
// 打印整型数组元素
printf("打印整型数组%s:\n",arrayName);
for(int i = 0; i < length; i++)
{
printf("%d, ",arr[i]);
}
printf("\n");

printf("printIntArray() finished...\n\n");
}

void printFloatArray(char * arrayName, float * arr, int length)
{
// 如果在函数内用sizeof来获得数组长度,会发现数组退化成了指针,获得的只是指针的长度
printf("\nprintFloatArray() loading...\n");

printf("Float array length is: %d\n",length);
printf("浮点型数组有%d个元素\n",length);
//打印浮点数组元素
printf("打印浮点数组:%s\n",arrayName);
for(int i = 0; i < length; i++)
{
printf("%f, ",arr[i]);
}
printf("\n");

printf("printFloatArray() finished...\n\n");
}

void printDoubleArray(char * arrayName, double * arr, int length)
{
// 如果在函数内用sizeof来获得数组长度,会发现数组退化成了指针,获得的只是指针的长度
printf("\nprintDoubleArray() loading...\n");
printf("Double array length is: %d\n",length);
printf("双精度型数组有%d个元素\n",length);
// 打印双精度数组元素
printf("打印双精度数组:%s\n",arrayName);
for(int i = 0; i < length; i++)
{
printf("%lf, ",arr[i]);
}
printf("\n");

printf("printDoubleArray() finished...\n\n");
}


void getCharArrayCount(char * arr)
{
int count = 0;

// 变量必须是左值才能自增,数组表达的是一个固定的地址值,不能自增,所以必须先定义指针变量p指向数组arr,用p来执行指针运算进行自增
char * p = arr;
while(*p++ !='\0')
{
count++;
}
printf("FYI: 地址为 %p 的字符串数组总共有 %d 个字符\n", &arr, count);
}


void arrayElementAddressDistanceTest()
{
printf("\nArrayAddressDistanceTest() Loading...\n");
//定义不同数据类型的数组及数组元素
char c[] = "JohnnyH";
int e[6] = {11,22,33,44,55,66};
float f[6] = {0.1f,0.2f,0.3f,0.4f,0.5f,0.6f};
double g[6] = {0.1,0.2,0.3,0.4,0.5,0.6};

/* 小数也可以使用 printf 函数输出,包括十进制形式和指数形式,它们对应的格式控制符分别是:
%f 以十进制形式输出 float 类型;
%lf 以十进制形式输出 double 类型;
%e 以指数形式输出 float 类型,输出结果中的 e 小写;
%E 以指数形式输出 float 类型,输出结果中的 E 大写;
%le 以指数形式输出 double 类型,输出结果中的 e 小写;
%lE 以指数形式输出 double 类型,输出结果中的 E 大写。
*/
// 输出字符串数组c

// 输出字符串数组的长度
char * charDataType = "char";
char * charArrayName = "c";
int sizeOfDataType = getSizeOfDataType(charDataType);
int charArrayLength = sizeof(c)/sizeOfDataType;
printCharArray(charArrayName,c,charArrayLength);

// 输出整形数组e
char * intDataType = "int";
char * intArrayName = "e";
sizeOfDataType = getSizeOfDataType(intDataType);
int intArrayLength = sizeof(e)/sizeOfDataType;
printIntArray(intArrayName,e,intArrayLength);

// 输出浮点数组f
char * floatDataType = "float";
char * floatArrayName = "f";
sizeOfDataType = getSizeOfDataType(floatDataType);
int floatArrayLength = sizeof(f)/sizeOfDataType;
printFloatArray(floatArrayName, f, floatArrayLength);

// 输出双精度数组g
char * doubleDataType = "double";
char * doubleArrayName = "g";
sizeOfDataType = getSizeOfDataType(doubleDataType);
int doubleArrayLength = sizeof(g)/sizeOfDataType;
printDoubleArray(doubleArrayName, g, doubleArrayLength);

// 输出各个数组头4个元素的地址
// %p表示按十六进制输出数据,如果输出数据不够8位数,则左边补零
// 不同数据类型的数组元素地址的间隔不同,char间隔1,int间隔4,float间隔4,double间隔8
printf("c[0] -> %p, c[1] -> %p, c[2] -> %p, c[3] -> %p\n",&c[0],&c[1],&c[2]);
printf("e[0] -> %p, e[1] -> %p, e[2] -> %p, e[3] -> %p\n",&e[0],&e[1],&e[2]);
printf("f[0] -> %p, f[1] -> %p, f[2] -> %p, f[3] -> %p\n",&f[0],&f[1],&f[2]);
printf("g[0] -> %p, g[1] -> %p, g[2] -> %p, g[3] -> %p\n",&g[0],&g[1],&g[2]);

// 定义字符类型指针变量pe并指向数组e
int * pe = e;

//输出字符串数组d的第一元素d[0]、第二元素d[1]、第三元素d[2]的值和地址
printf("*pe的值是:%d\npe的值是一个地址:%p\n", *pe,e);
printf("*(pe + 1)的值是:%d\n(pe + 1)的值是一个地址:%p\n", *(pe + 1),(pe+1));
printf("*(pe + 2)的值是:%d\n(pe + 2)的值是一个地址:%p\n", *(pe + 2),(pe+2));

printf("ArrayAddressDistanceTest() Finished...\n\n");
}


void pointerAddressTest()
{
// 定义字符变量a和整型变量f并初始化
printf("\nPointAddressTest() Loading...\n");
char c = 'F';
int b = 123;

// 指针变量必须初始化,否则会成为野指针。
// 指针即地址,虽然指针变量存的是地址,但指针变量不等同于指针

// 用char*定义字符指针变量pa并初始化,这时指针变量pc存储的是变量a的地址,即指针变量pc指向a的地址
char * pc = &c;
// 用int*定义整型指针变量pb并初始化,这时指针变量pb存储的是变量b的地址,即指针变量pb指向b的地址
int * pb = &b;

// 输出指针变量pa和pb的值
printf("a的值是: %c\n", *pc);
printf("f的值是: %d\n", *pb);

// *pa是指从pa所存的地址(根据指针初始化,pa存的是a的地址)找到a,然后对a的数值进行赋值。
* pc = 'C';
// *pb是指从pb所存的地址(根据指针初始化,pb存的是f的地址)找到f,然后对f的数值进行赋值。
* pb += 1;

// 输出指针变量pa指向的地址(即a的地址)所存储的值(即a的值),发现已经被修改
printf("对字符串变量a地址的内存进行赋值,现在a的值是: %c\n", * pc);
// 输出指针变量pb指向的地址(即a的地址)所存储的值(即a的值),发现已经被修改
printf("对整形变量b地址的内存进行赋值,现在b的值是: %d\n", * pb);

/* 输出指针变量的长度(一个指针变量容量有多少个字节),不同的编译系统的指针变量的长度不同。
64位系统是8字节,32位系统是4字节。
*/
printf("指针变量pa的长度是: %d\n",sizeof(pc));
printf("指针变量pb的长度是: %d\n",sizeof(pb));

// 定义一个整形变量c
int d = 666;
//定义个指针变量pc,pc指向c的地址
int * pd = &d;

// 输出c的地址
printf("c的地址是:%x\n", &d);
// 输出指针变量pc的值,可以发现就是c的地址
printf("指针变量pc的值是一个地址:%x\n", pd);

printf("c的值是:%d\n",d);
// 指针变量pd的值就是d变量的地址,现在对d地址的内存进行赋值,那么变量d的值就被改为233
*pd = 233;
printf("用指针变量pc对c地址的内存进行赋值,现在c的值为:%d\n", *pd);

printf("pointerAddressTest() finished...\n\n");
}


void pointerArrayTest1()
{
printf("\npointerArrayTest1() loading...\n");

int b = 55;
int d = 44;
int e = 33;
int f = 22;
int g = 11;

// 定义一个整型指针数组
int *p[5] = {&b, &d, &e, &f, &g};

// 定义一个整型数组
int a[5] = {b,d,e,f,g};

printf("整型指针数组p的值是 %p\n", p);
printf("整型指针数组p的地址是 %p\n", &(*p));
printf("整型指针数组p的第一个元素*p[0]的地址是%p\np[0]的值是%p\nb的值是 %d\n", &(*p[0]), p[0], *(&b));
printf("整型数组a的地址是 %p\na[0]的地址是%p\nb的值是 %d\n", a, &a[0], b);

int * hello = * p;
int * world = a;

// 如果在非main函数内用sizeof来获得数组长度,会发现数组被传址到了函数里就退化成了指针
// 对函数内的数组用sizeof获得的只是其指针的长度,因此要在数组所在的函数先计算出数组长度再传参到其他函数

// 用数组传址方式调用函数来输出数组
char * intPointerDataType = "int *";
char * intPointerArrayName = "p";
int sizeOfDataType = getSizeOfDataType(intPointerDataType);
int intPointerArrayLength = sizeof(p)/sizeOfDataType;
printIntPointerArray(intPointerArrayName,p,intPointerArrayLength);

char * intDataType = "int";
char * intArrayName = "a";
sizeOfDataType = getSizeOfDataType(intDataType);
int intArrayLength = sizeof(a)/sizeOfDataType;
printIntArray(intArrayName,a,intArrayLength);


printf("当前*hello的值是:%d\n", *hello);
printf("当前*hello的地址是:%p\n", hello);
printf("sizeof(hello):%d\n", sizeof(hello));

// 直接用for循环,打印指针数组p的元素、元素地址、指针自减
for(int i = 0;i < 5;i++)
{
printf("*p[%d]的值是:%d ", i, *p[i]);
printf("*hello的值是:%d ", *hello);
printf("*p[%d]的地址是:%p ", i, p[i]);
printf("指针hello--自减前的值是:%p\n", hello--);
}

printf("当前*world的值是:%d\n", *world);
printf("当前*world的地址是:%p\n", world);
printf("sizeof(world):%d\n", sizeof(world));

// 直接用for循环打印整型数组a的元素、元素地址、指针自增
for(int i = 0;i < 5;i++)
{
printf("a[%d]的值是:%d ", i,a[i]);
printf("*world的值是:%d ", *world);
printf("a[%d]的地址是:%p ", i, &a[i]);
printf("指针world++自增前的值是:%p\n", world++);
}
printf("\n");
printf("\npointerArrayTest1() finished...\n");
}

void pointerArrayTest2()
{
printf("\npointerArrayTest2() loading...\n");

// 定义一个字符串指针数组str
char * str = "Continuous attention to technical excellence and good design enhances agility\n";
// 打印字符串str
printf(str);
// 得出字符串数组str的字符个数
getCharArrayCount(str);

// 调用函数方式打印字符串str
char * charDataType = "char";
char * charArrayName = "str";
int sizeOfDataType = getSizeOfDataType(charDataType);
int charArrayLength = sizeof(str)/sizeOfDataType;
printCharArray(charArrayName,str,charArrayLength);

// 输出数组str的地址
printf("字符串数组str的地址是:%p\n",&str);
// 输出数组的第一个元素的地址,可见就是数组str的地址
printf("数组str的第一个元素str[0]的地址是:%p\n",&str[0]);

printf("pointerArrayTest2() finished...\n\n");
}

void pointerArrayTest3()
{
printf("\npointerArrayTest3() loading...\n");
//字符数组(指针数组)
char * pStr[5] = {
"欲穷千里目",
"曲项向天歌",
"疑是地上霜",
"野渡无人舟自横",
"Impossible is nothing!"
};
int length = 5;
getCharArrayCount(pStr);

// 直接用for循环来打印字符串类型指针数组
printf("字符串类型指针数组pStr的地址是:%p\n", pStr);
for(int i = 0; i <length; i++)
{
printf("%s ",pStr[i]);
}
printf("\n");

// 调用函数传参传址方式打印字符串类型指针数组
char * charPointDataType = "char *";
char * charPointArrayName = "p";
int sizeOfDataType = getSizeOfDataType(charPointDataType);
int charArrayLength = sizeof(pStr)/sizeOfDataType;
printCharPointArray(charPointArrayName,pStr,charArrayLength);

printf("\npointerArrayTest3() finished...\n\n");
}

int main()
{
printf("main() loading...\n");

// 指针地址测试
pointerAddressTest();

// 数组元素地址和指针的关系
arrayElementAddressDistanceTest();

// 指针数组测试一
pointerArrayTest1();

// 指针数组测试二
pointerArrayTest2();

// 指针数组测试三
pointerArrayTest3();

printf("main() finished...\n");

return 0;
}

标签:传址,int,char,数组,printf,sizeof,指针
来源: https://www.cnblogs.com/johnnyH/p/15705650.html