C语言 指针、地址、指针变量、基本类型数组、指针数组、函数传参、数组传址、sizeof
运行结果截图(代码在截图下面):
(如果不想看过程提示信息就注释掉函数里相应的那些printf语句即可)
代码:
#include <stdio.h>
#include <string.h>
int getSizeOfDataType(char * dataType)
{
//printf("\ngetSizeofDataType() loading...\n");
int size;
// 用if...else if...来执行对所传入的不同数据类型的判断,计算和输出某个数据类型的最小单元所占的字节数size
if (0 == strcmp(dataType, "char") )
{
size = sizeof(char);
// printf("sizeof(char):%d\n", size);
}else if (0 == strcmp(dataType, "char *") )
{
size = sizeof(char *);
// printf("sizeof(char *):%d\n", size);
}else if (0 == strcmp(dataType, "int") )
{
size = sizeof(int);
// printf("sizeof(int):%d\n", size);
}else if (0 == strcmp(dataType, "int *") )
{
size = sizeof(int *);
// printf("sizeof(int *):%d\n", size);
}else if (0 == strcmp(dataType, "short") ) {
size = sizeof(short);
// printf("sizeof(short):%d\n", size);
}else if (0 == strcmp(dataType, "long") ) {
size = sizeof(long);
// printf("sizeof(long):%d\n", size);
}else if (0 == strcmp(dataType, "long long int") )
{
size = sizeof(long long int);
// printf("sizeof(long long int):%d\n", size);
}else if (0 == strcmp(dataType, "float") ) {
size = sizeof(float);
// printf("sizeof(float):%d\n", size);
}else if (0 == strcmp(dataType, "double") ) {
size = sizeof(double);
// printf("sizeof(double):%d\n", size);
}else
{
printf("!!! Error:Unknown datatype: %s, please contact IT support for further fix...\n",dataType);
size = 0;
}
// int addressSizeCheck = 0;
// printf("sizeof(internalStorageAddressSize):%d\n",sizeof(&addressSizeCheck));
// printf("getSizeofDataType() finished...\n\n");
return size;
/* 注意:为什么不用switch?switch的表达式必须是int整型,否则编译不通过!且有break语句容易破坏代码结构性而出错。
* 以下为switch的语法结构:
*
* switch(expression)
* {
* case constant-expression:
* statement(s);
break;
case constant-expression:
statement(s);
break;
default:
statement(s);
}
*/
}
void getCharArrayCount(char * arr)
{
int count = 0;
// 变量必须是左值才能自增,数组表达的是一个固定的地址值,不能自增,所以必须先定义指针变量p指向数组arr,用p来执行指针运算进行自增
char * p = arr;
while(* p++ != '\0')
{
count++;
}
printf("地址为 %p 的字符数组总共有%2d个字符。", arr, count);
}
void printCharPointArray(char * arrayName, char * * arr, int length)
{
// 如果在函数内用sizeof来获得函数外传入的数组长度,会发现数组退化成了指针,获得的只是指针的长度,因此要在函数外计算出数组长度再传进函数里
//printf("\nprintCharPointerArray() loading...\n");
int i;
// 打印字符指针数组元素
//printf("字符指针数组长度为%d个char * 类型单元的长度\n",length);
//printf("字符指针数组%s的地址是:%p\n", arrayName, arr);
//printf("\n以函数内的(pArr + i)为指针打印字符指针数组%s:~~~~~~~~~~~~~~~\n\n", arrayName);
for(i = 0; i < length; i++)
{
// printf("字符指针数组第%d个元素是一个地址:%p\n", i, (pArr + i));
// printf("对于字符指针数组第%d个元素,以*解引用:\n%s\n", i);
printf("%s\n", * (arr + i));
}
printf("\n");
/* printf("\n以函数内的pArr为指针,以pArr++自增方式打印字符指针数组%s:~~~~~~~~~~~~~~~\n\n", arrayName);
pArr = arr;
for(i = 0; i < length; i++)
{
printf("字符指针数组第%d个元素是一个地址:%p\n", (i + 1), pArr);
printf("以字符指针数组第%d个元素为地址所存储的值是:\n%s\n", (i + 1), * pArr++);
}
*/
// printf("printCharPointerArray() finished...\n\n");
}
void printIntPointerArray(char * arrayName, int * * pointerOfArray, int length)
{
// 如果在函数内用sizeof来获得函数外传入的数组长度,会发现数组退化成了指针,获得的只是指针的长度,因此要在函数外计算出数组长度再传进函数里
// printf("\nprintIntPointerArray() loading...\n");
// 打印指针数组元素
// printf("int * array length is: %d\n", length);
// printf("整型指针数组的长度为%d个int * 类型单元的长度\n", length);
// printf("整型指针数组%s的地址是:%p\n", arrayName, pointerOfArray);
// printf("打印整型指针数组%s:\n", arrayName);
//定义一个左值指针变量,以便进行指针运算
int * * pArr = pointerOfArray;
// printf("\n以函数内的pArr为指针,以 * (pArr + i)为指针的方式打印字符指针数组%s:~~~~~~~~~~~~~~~\n\n", arrayName);
for(int i = 0; i < length; i++)
{
//printf("整型指针数组第%d个元素的值是%p,对该元素用 * 解引用的值是:\n", (i + 1), * (pArr + i));
printf("%5d", * * (pArr + i));
}
printf("\n");
// printf("printIntPointerArray() finished...\n\n");
}
void printCharArray(char * arrayName, char * arr, int length)
{
// 如果在函数内用sizeof来获得函数外传入的数组长度,会发现数组退化成了指针,获得的只是指针的长度
//printf("\nprintCharArray() loading...\n");
// 打印字符数组元素
//printf("int * array length is: %d\n", length);
// printf("字符数组的长度为%d个char类型单元的长度\n", length);
//printf("当前字符数组%s的地址是:%p\n", arrayName, arr);
// 打印字符数组的字符数
//getCharArrayCount(arr);
// 打印字符数组元素
char * pArr = arr;
printf("%s\n", pArr);
//printf("printCharArray() finished...\n\n");
}
void printIntArray(char * arrayName, int * arr, int length)
{
// 如果在函数内用sizeof来获得函数外传入的数组长度,会发现数组退化成了指针,获得的只是指针的长度
//printf("\nprintIntArray() loading...\n");
//printf("Int array length is: %d\n", length);
//printf("整型数组的长度为%d个int类型单元的长度\n", length);
// 打印整型数组元素
//printf("打印整型数组%s:\n",arrayName);
for(int i = 0; i < length; i++)
{
printf("%5d", 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个float类型单元的长度\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个double类型单元的长度\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 testArrElemAddressDistance()
{
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};
char * charDataType = "char";
char * charArrayName = "c";
char * intDataType = "int";
char * intArrayName = "e";
char * floatDataType = "float";
char * floatArrayName = "f";
char * doubleDataType = "double";
char * doubleArrayName = "g";
int sizeOfDataType;
int charArrayLength;
int intArrayLength;
int floatArrayLength;
int doubleArrayLength;
/* 定义一个char * 类型的指针变量pc,并将其初始化。这里初始化是将指针变量pc指向了字符数组c
在C语言中相当于指向了字符数组c的第一个元素c[0])
*/
char * pc = c;
// 输出字符数组c
sizeOfDataType = getSizeOfDataType(charDataType);
charArrayLength = sizeof(c) / sizeOfDataType;
printCharArray(charArrayName, c, charArrayLength);
// 输出整型数组e
sizeOfDataType = getSizeOfDataType(intDataType);
intArrayLength = sizeof(e) / sizeOfDataType;
printIntArray(intArrayName, e, intArrayLength);
// 输出浮点数组f
sizeOfDataType = getSizeOfDataType(floatDataType);
floatArrayLength = sizeof(f) / sizeOfDataType;
printFloatArray(floatArrayName, f, floatArrayLength);
// 输出双精度数组g
sizeOfDataType = getSizeOfDataType(doubleDataType);
doubleArrayLength = sizeof(g) / sizeOfDataType;
printDoubleArray(doubleArrayName, g, doubleArrayLength);
printf("\n");
// 输出各个数组头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], &c[3]);
printf("e[0] -> %p, e[1] -> %p, e[2] -> %p, e[3] -> %p\n", &e[0], &e[1], &e[2], &e[3]);
printf("f[0] -> %p, f[1] -> %p, f[2] -> %p, f[3] -> %p\n", &f[0], &f[1], &f[2], &f[3]);
printf("g[0] -> %p, g[1] -> %p, g[2] -> %p, g[3] -> %p\n", &g[0], &g[1], &g[2], &g[3]);
printf("\n");
// 输出各个数组第4个元素的值
printf("c[3]的值是%c e[3]的值是%d f[3]的值是%f g[3]的值是%lf\n", * (pc + 3), e[3], f[3], g[3]);
// 定义字符类型指针变量pe并指向数组e
printf("以 (int * pe = e;) 方式定义一个整型指针 int * pe 并立即对指针 pe 进行初始化;\n");
int * pe = e;
// 输出字符数组d的第一元素d[0]、第二元素d[1]、第三元素d[2]的值和地址
printf("对整型指针pe用 * 解引用的值是:%d\n pe 的值是一个地址:%p\n", * pe, e);
printf("用 * 对整型指针(pe + 1)解引用,即 * (pe + 1),其值为:%d\n整型指针(pe + 1)的值是一个地址:%p\n", * (pe + 1), (pe + 1));
printf("用 * 对整型指针(pe + 2)解引用,即 * (pe + 2),其值为:%d\n整型指针(pe + 2)的值是一个地址:%p\n", * (pe + 2), (pe + 2));
printf("ArrayAddressDistanceTest() Finished...\n\n");
/* 对于指针变量:
* 如果定义了一个指针变量并初始化指向某个数组或变量或地址,
* 那么指针变量的值通常就是某个具体的地址数值。
* 某个具体的地址数值对应的是内存中的某个具体且唯一的物理位置,这个物理位置是固定的。
* 指针变量可以表达复杂的数据关系,实现复杂的数据结构。
* 但指针的操作对于不熟悉指针原理的编程者来说,也是一把双刃剑。
* 指针变量的值在用 * 解引用前,无论怎么改变指针变量自身的值,
* 都只是表达对某个存储空间的定位,并不对其进行读写。
* 通过对指针变量用 * 解引用,可以对指针变量指向的地址所对应的某段空间进行直接的读写,
* 可以实现高效率的数据传输。
* 指针变量解引用后,也相当于打开了潘朵拉魔盒,因为如果指针定位不准确,
* 解引用后的读操作会导致读出错误的数据,而写操作就可能会带来不可逆转的后果。
*
* 举个例子,如果p被定义为int类型指针变量,a被定义为一个int类型的变量,
* p被初始化值为一个数值为00000019fbfff790的地址,这个地址对应的内存当前存有一个int类型的数值66,
* 那么表达式 a = * p 就相当于:先执行 * p,也就是对p用 * 解引用,
* 读取了地址为00000019fbfff790对应的内存里存的 66,
* * p运算返回的结果就是66,然后执行a = 66,也就是把 66 赋值给int类型的变量a
* 而表达式 a = 99; * p = a,则是先执行 a = 99,把99赋值给变量a,
* 然后执行 * p,也就是对p用 * 解引用,获得与p所指向的地址00000019fbfff790相对应的存储空间
* 的读写权限,最后执行 * p = a,把变量a的数值 99 写入这段存储空间,
* 那么这段存储空间所存的数值就被修改为99,由于指针变量p的值并未改变,还是指向这个空间的地址,
* 所以用printf打印输出 * p的值,可以看到是99
*/
/* 指针变量的自增,是指针变量 + 1然后赋值给指针变量自身。
* 多数情况下,指针变量自增后的值不能被简单的当做(指针变量的原地址数值 + 1)。
* 指针变量自增后它的值变为一个新地址数值,
* 这个新地址数值与自增前指针变量的值(原地址数值)是有一定的跨度(地址差)的。
* (指针变量 + 1)是表达了一个有参照物的地址,指针变量的值只是被参照,并没有被改变。
* 而指针变量++,则是指针变量的值被改变,指针变量指向了新地址。
* 将指针变量自增前的值与自增后的值作比较,是跨1个地址单元还是跨多个地址单元,
* 由这个指针变量类型所占空间决定。
*/
/* 举个例子,如果pc是一个字符指针变量,且被初始化为指向了字符数组c(也就是
* 指向了数组c的第一个元素c[0]),
* 那么(pc + 1)的值就是比pc向前跨1个指针的地址,
* 也就是(pc + 1)指向了数组a的第二个元素c[1]的地址,可见这里的pc和 + 1都参与了对指针的定位,
* 注意这时pc没有自增,pc本身的值并没有被改变。
* 表达式 * (pc + 1)是指对(pc + 1)用 * 解引用,返回的是c[1]的值。
* 同理,*(pc + 3)是指对(pc + 3)用 * 解引用,返回的就是c[3]的值
* 表达式(* pc + 1)表达的是对指针变量pc用 * 解引用得到的值(即数组c
* 第一个元素c[0]的值'J')进行 + 1运算,
* 这里的+ 1没有参与对指针的定位。
* 再举一个例子:假设p是一个指针变量,那么表达式(++ * p)相当于 * p =((* p)+ 1),
* 是针对(* p)的自增,可见 + 1没有参与指针定位;
* 而表达式(* p++)则是先执行(* p)再执行p = (p + 1),是针对p的自增,
* 可见 + 1和 p 都参与了指针的定位。
*
* 结论是————如果要表达指针的变化,表达式要用 * (p + i) 或者用 (* p++)的形式,
* 不同的是,前者p值不变,如果用(p + i)的值代表指针,则指针的位置比p朝前跳 i 个指针单元;
* 而后者是对p值自增,直接用p的值代表指针位置。
*/
}
void testPointerAddress()
{
// 定义字符变量a和整型变量f并初始化
printf("\nPointAddressTest() Loading...\n");
char c = 'F';
int b = 123;
// 指针变量必须初始化,否则会成为野指针。
// 指针即地址,虽然指针变量存的是地址,但指针变量不等同于指针
// 用char * 定义字符指针变量pc并初始化,这时指针变量pc存储的是变量a的地址,即指针变量pc指向a的地址。
// 注意: * pc不是指针变量,pc才是指针变量。
char * pc =&c;
// 用int * 定义整型指针变量pb并初始化,这时指针变量pb存储的是变量b的地址,即指针变量pb指向b的地址
// 注意: * pb不是指针变量,pb才是指针变量。
int * pb =&b;
// 输出指针变量pa和pb的值
printf("a的值是: %c\n", * pc);
printf("f的值是: %d\n", * pb);
// * pc 是指:从指针变量pc所存的地址,获得这个地址所存储的数据。在这里是获得变量c的数据。
// * pc 又称为————对指针变量pc用 * 进行解引用,在这里解引用的返回值是变量c的值。
// 由于这里的 * pc 的运算结果返回的是变量c的值, 所以 * pc = 'C'就相当于c = 'C',也就是把字符类型的'C'赋值给变量c
* pc = 'C';
// * pb是指从指针变量pb所存的地址(根据指针初始化,pb存的是b的地址)找到f(又称为对指针变量pb用 * 进行解引用)
// 在本例中, * pb 的运算结果返回的是变量b, 所以 (* pb += 1 )就相当于(b += 1)。
* pb += 1;
// 输出指针变量pa指向的地址(即c的地址)所存储的值(即c的值),发现已经被修改
printf("对字符变量c所指向的地址的内存进行赋值,现在c的值是: %c\n", * pc);
// 输出指针变量pb指向的地址(即a的地址)所存储的值(即a的值),发现已经被修改
printf("对整型变量b所指向的地址的内存进行赋值,现在b的值是: %d\n", * pb);
/* 输出整型指针变量的长度。
指针变量的长度是指对指针变量所存的数据进行解引用,所得到的数据的长度。不同的编译系统不同的数据类型的指针变量的长度不同。
指针变量所存的数据,其内容是一个地址,这个地址指向了某个数值或变量,指针变量的长度就是指的这个数值或变量的长度。
内存地址占的长度一般是long类型,例如64位系统地址长度是8字节,32位系统则是4字节。
*/
printf("指针变量pc的长度是: %d个字节\n", sizeof(pc));
printf("指针变量pb的长度是: %d个字节\n", sizeof(pb));
// 定义一个整型变量d
int d = 666;
// 定义个指针变量pd,pd指向d的地址
int * pd =&d;
// 输出c的地址
printf("变量d的地址是:%x\n", &d);
// 输出指针变量pc的值,可以发现就是c的地址
printf("指针变量pd的值是一个地址:%x\n", pd);
printf("d的值是:%d\n", d);
// 指针变量pd的值就是d变量的地址,现在对d地址的内存进行赋值,那么变量d的值就被改为233
* pd = 233;
printf("用指针变量pd对d地址的内存进行赋值,现在d的值为:%d\n", * pd);
printf("pointerAddressTest() finished...\n\n");
}
void testPointerArray1()
{
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};
// 指针类型的变量必须在定义后立即初始化,避免野指针
char * intPointerDataType = "int *";
char * intDataType = "int";
char * intPointerArrayName = "p";
char * intArrayName = "a";
int * world = a;
// 指向整型指针数组p的指针类型,需要定义为int * * 类型
printf("定义一个指向指针数组的指针变量,类型为int * * 类型\n");
int * * pForPointerArray = p;
int * * hello = p;
int i;
int sizeOfDataType;
int intPointerArrayLength;
int intArrayLength;
// 辨识指针数组的地址是哪个,指针数组的元素本身存的值也是一个地址
printf("\n整型指针数组p的值是:%p(也就是指针数组p向函数传递数据所需要提供的地址)\n", p);
printf("整型指针数组p用 * 解引用,那么 * p 的值是:%p,可见和 * p[0]的值相同\n", * p);
printf("整型指針數組第1个元素&b的值是:%p,可见和 * p[0]的值相同\n", &b);
printf("整型指針數組第1个元素 p[0](也即&b)的值是:%p\n", p[0]);
printf("对整型指针数组第1个元素 p[0](也即&b)用 * 解引用,那么 * p[0]的值是: %d\n", * p[0]);
printf("对整型指針數組第1个元素用&取地址,那么&p[0]的值是:%p,可见和p的值相同\n", &p[0]);
printf("整型指針數組第5个元素&g 的值是一个地址:%p\n", &g);
printf("整型指針數組第5个元素 p[4](也即&g)的值是:%p\n", p[4]);
printf("对整型指针数组第5个元素 p[4](也即&g)用 * 解引用,那么 * p[4]的值是: %d\n", * p[4]);
printf("对整型指針數組第5个元素用&取地址,&p[4]的值是:%p\n", &p[4]);
printf("\n现在用指针来输出指针数组p的个别元素(在代码中需将指针数组赋值给左值,以便用左值进行指针运算)~~~\n");
printf("整型指针 * pForPointerArray的值是:%p,和p[0]的值相同\n", * pForPointerArray);
printf("对整型指针 * pForPointerArray用 * 解引用,那么 * * pForPointerArray的值是:%d,可见和 * p[0](也即 * (&b))的值相同\n", * * pForPointerArray);
printf("对整型指针pForPointerArrayP用&取地址: %p,这样的取地址没意义~~~\n", &pForPointerArray);
printf("整型指针数组p的第1个元素,即 * (pForPointerArray + 0)的值是:%p\n", * (pForPointerArray + 0));
printf("对整型指针数组p的第1个元素,即 * (pForPointerArray + 0)用 * 解引用,那么 * * (pForPointerArray + 0)的值是:%d\n", * * (pForPointerArray + 0));
printf("整型指针数组p的第5个元素(即 * (pForPointerArray + 4))的值是:%p\n", * (pForPointerArray + 4));
printf("对整型指针数组p的第5个元素(即 * (pForPointerArray + 4)) 用 * 解引用,那么 * * (pForPointerArray + 4)的值是:%d\n", * * (pForPointerArray + 4));
printf("\n现在对整型数组a的个别元素直接进行输出(不涉及指针运算)~~~\n");
printf("整型数组a的值是 %p\n", a);
printf("对整型数组a用&取地址,发现和a的值一样:%p\n", &a);
printf("整型数组的第1个元素a[0]的地址是:%p,a[0]的值是%d\n", &a[0], a[0]);
printf("整型数组的第5个元素a[4]的地址是:%p,a[4]的值是%d\n", &a[4], a[4]);
// 如果在非main函数内用sizeof来获得数组长度,会发现数组被传址到了函数里就退化成了指针
// 对函数内的数组用sizeof获得的只是其指针的长度,因此要在数组所在的函数先计算出数组长度再传参到其他函数
// 调用函数输出整型指针数组p
sizeOfDataType = getSizeOfDataType(intPointerDataType);
printf("intPointerArrayLength = sizeof(p) / sizeOfDataType\nintPointerArrayLength:%d\n",intPointerArrayLength = sizeof(p) / sizeOfDataType);
printf("\n现在用int * * 类型的指针传递指针数组p的地址给函数printIntPointerArray(),并在函数内用 int * * 类型的指针输出指针数组p~~~\n");
printIntPointerArray(intPointerArrayName, pForPointerArray, intPointerArrayLength);
// 直接用for循环,打印指针数组p的元素、元素地址、并测试指针移动
printf("\n现在直接用for循环,打印指针数组p的元素、元素地址、并测试指针移动~~~\n\n");
for(i = 0; i < 5; i++)
{
printf("数组的第%d个元素p[%d]的地址是:%p", (i + 1), i, p[i]);
printf("对p[%d]用 * 解引用:%d\n", i, * p[i]);
printf("指针 * (hello + i)的值是:%p", * (hello + i));
printf("对指针 * (hello + i)用 * 解引用:%d\n", * * (hello + i));
}
printf("\n");
// 用调用函数方式来输出整型指针数组a
printf("\n现在向函数直接传递数组,通过函数输出数组a~~~\n");
sizeOfDataType = getSizeOfDataType(intDataType);
intArrayLength = sizeof(a) / sizeOfDataType;
printIntArray(intArrayName, a, intArrayLength);
// 直接用for循环打印整型数组a的元素、元素地址、指针自增
printf("\n现在直接用for循环打印整型数组a的元素、元素地址、并测试指针移动~~~\n\n");
for(i = 0; i < 5; i++)
{
printf("数组的第%d个元素a[%d]的地址是:", (i + 1), i &a[i]);
printf("a[%d]的值是:%d。", i, a[i]);
printf("指针(world + i)的值是:%p", (world + i));
printf("对指针(world + i)用 * 解引用:%d\n", * (world + i));
}
printf("\n");
printf("\npointerArrayTest1() finished...\n");
}
void testPointerArray2()
{
printf("\ntestPointerArray2() loading...\n");
//定义字符数组str
char * str[12] = {
"Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.",
"Welcome changing requirements, even late in development.Agile processes harness change for the customer's competitive advantage.",
"Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.",
"Business people and developers must work together daily throughout the project.",
"Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done.",
"The most efficient and effective method of conveying information to and within a develop team is face-to-face conversation.",
"Working software is the primary measure of progress.",
"Agile process promote sustainable development. The sponsors, developers and users should be able to maintain a constant pace indefinitely",
"Continuous attention to technical excellence and good design enhances agility.",
"The best architectures, requirements and designs emerge from self-organizing teams",
"Simplicity--the art of maximizing the amount of work not down--is essential.",
"At regular intervals, the team reflects on how to be more effective, then tunes and adjusts its behavior accordingly."
};
char * charPointerDataType = "char *";
char * charPointerArrayName = "str";
char * charDataType = "char";
char * charArrayName = "Str";
int sizeOfDataType;
int charPointArrayLength;
int charArrayLength;
int i;
//输出字符指针数组str的地址
printf("\n\n请一字不差的背诵《敏捷12原则英文版》:\n");
printf("\n字符指针数组str的地址是~~~~~%p\n", str);
// 直接for循环打印字符指针数组str
printf("\n~~~~~~~~~~~~~~~现在直接以for循环方式打印字符指针数组~~~~~~~~~~~~~~~\n\n");
for (i = 0; i < 12; i++) {
//printf("字符指针数组str的地址是~~~~~%p\n", str);
// 用strlen()得出字符数组str的字符个数
//printf("用strlen()来统计,当前字符数组总共有 %d 个字符\n", strlen(* (str + i)));
// 调函数方式得出字符数组的字符个数,应该和用strlen()来统计的结果是一致的
//getCharArrayCount(* (str + i));
printf("%s\n", * (str + i));
}
//调用函数方式打印字符指针数组str
printf("\n~~~~~~~~~~~~~~~现在以向函数传递字符指针数组地址的方式逐个打印字符指针数组~~~~~~~~~~~~~~~\n\n");
sizeOfDataType = getSizeOfDataType(charPointerDataType);
charPointArrayLength = sizeof(str) / sizeOfDataType;
printCharPointArray(charPointerArrayName, str, charPointArrayLength);
// for循环方式逐个打印字符指针数组元素
printf("\n~~~~~~~~~~~~~~~现在以for循环方式向函数传递字符数组地址的方式逐个打印字符指针数组元素:~~~~~~~~~~~~~~~\n\n");
sizeOfDataType = getSizeOfDataType(charDataType);
for (i = 0; i < charPointArrayLength; i++)
{
//printf("字符指针数组str的地址是~~~~~%p\n", str);
charArrayLength = sizeof(* (str + i)) / sizeOfDataType;
printCharArray(charArrayName, * (str + i), charArrayLength);
}
// 输出数组str的地址
printf("字符指针数组str的地址是:~~~~~%p\n", str);
// 输出字符指针数组的元素的地址,可见第一个元素的地址就是数组str的地址
printf("字符指针数组str的第一个元素str[0]的地址是:%p\n", &str[0]);
printf("字符指针数组str的倒数第一个元素str[11]的地址是:%p\n", &str[11]);
printf("\ntestPointerArray2() finished...\n\n");
}
void testPointerArray3()
{
printf("\npointerArrayTest3() loading...\n");
//字符数组(指针数组)
char * Str[5] = {
"欲穷千里目",
"曲项向天歌",
"疑是地上霜",
"野渡无人舟自横",
"Impossible is nothing!"};
char * charPointDataType = "char *";
char * charPointArrayName = "p";
int length = 5;
int sizeOfDataType;
int charArrayLength;
int i;
// 直接用for循环来打印字符类型指针数组
printf("\n~~~~~~~~~~~~~~~现在直接以for循环方式打印字符指针数组~~~~~~~~~~~~~~~\n\n");
for (i = 0; i < length; i++)
{
printf("%s\n", Str[i]);
}
printf("\n");
// 调用函数传参方式打印字符类型指针数组
printf("\n~~~~~~~~~~~~~~~现在以向函数传递字符指针数组地址的方式逐个打印字符指针数组~~~~~~~~~~~~~~~\n\n");
sizeOfDataType = getSizeOfDataType(charPointDataType);
charArrayLength = sizeof(Str) / sizeOfDataType;
printCharPointArray(charPointArrayName, Str, charArrayLength);
printf("字符指针数组Str的地址是:~~~~~%p\n", Str);
printf("\npointerArrayTest3() finished...\n\n");
}
int main()
{
printf("main() loading...\n");
// 基本的指针地址测试(已测试通过)
testPointerAddress();
// 数组元素地址和指针的关系(已测试通过)
testArrElemAddressDistance();
// 指针数组测试一(已测试通过)
testPointerArray1();
// 指针数组测试二(已测试通过)
testPointerArray2();
// 指针数组测试三(已测试通过)
testPointerArray3();
printf("main() finished...\n");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】