64,654
社区成员
发帖
与我相关
我的任务
分享
# include <stdio.h>
int main(void)
{
char * p = "a\0b\0c\0\0\0";
char (*a)[2] = (char(*)[2])p;
int i;
for (i = 0; *a[i] != 0; i++)
{
printf("%s\n", a[i]);
}
return 0;
}
这有两个限制,每个子串包括结尾0必须等宽,同时,最尾部必须有个空串,以便能知道“数组”的结尾。
//这个意思??函数定义时就定义成数组指针
void arr(char (*p)[N],m)
{
int i=0;
for (;i<m;i++)
//...
}
void main
{
//....
char arry[5][N];
arr(arry,5);
}
// "abc\0","bcde\0" -> 这样的2个连续字符串,传到某个函数里面以后,想简化成
//
// *(a[2])
// a[0] -> 直接访问abc\0
// a[1] -> 直接访问bcde\0
//
// 或者
//
// "abc","bcde" -> 这样的2个连续字符数组,传到某个函数里面以后,想简化成
//
// *(a[2])
// a[0] -> 直接访问abc
// a[1] -> 直接访问bcde
#include <stdio.h>
#include <string.h>
char s1[]="1abc\0001bcde";
char *s2[2]={"2abc","2bcde"};
char s3[2][6] = {"3abc", "3bcde"};
char p1[5] = {'4', 'a', 'b', 'c', 0};
char p2[6] = {'4', 'b', 'c', 'd', 'e', 0};
char *s4[2]={p1,p2};
void func1(void *p) {
char *a[2];
a[0]=(char *)p;
a[1]=(char *)p+strlen((char *)p)+1;
printf("func1\n");
printf("a[0]==[%s],a[1]==[%s]\n",a[0],a[1]);
}
void func2(void *p) {
char *a[2];
a[0]=((char **)p)[0];
a[1]=((char **)p)[1];
printf("func2\n");
printf("a[0]==[%s],a[1]==[%s]\n",a[0],a[1]);
}
void func3(void *p) {
char *a[2];
a[0]=(char *)p;
a[1]=(char *)p+6;
printf("func3\n");
printf("a[0]==[%s],a[1]==[%s]\n",a[0],a[1]);
}
int main() {
func1(s1);
func2(s2);
func3(s3);
func2(s4);
return 0;
}
//func1
//a[0]==[1abc],a[1]==[1bcde]
//func2
//a[0]==[2abc],a[1]==[2bcde]
//func3
//a[0]==[3abc],a[1]==[3bcde]
//func2
//a[0]==[4abc],a[1]==[4bcde]
一切“技巧”都来自:
VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”
但我又不得不承认:
有那么些人喜欢或者适合用“先具体再抽象”的方法学习和理解复杂事物;
而另一些人喜欢或者适合用“先抽象再具体”的方法学习和理解复杂事物。
而我本人属前者。
这辈子不看内存地址和内存值;只画链表、指针示意图,画堆栈示意图,画各种示意图,甚至自己没画过而只看过书上的图……能从本质上理解指针、理解函数参数传递吗?本人深表怀疑!
这辈子不种麦不收麦不将麦粒拿去磨面;只吃馒头、吃面条、吃面包、……甚至从没看过别人怎么蒸馒头,压面条,烤面包,……能从本质上理解面粉、理解面食吗?本人深表怀疑!!
提醒:
“学习用汇编语言写程序”
和
“VC调试(TC或BC用TD调试)时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!
不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
有人说一套做一套,你相信他说的还是相信他做的?
其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗?
不要写连自己也预测不了结果的代码!
// "abc\0","bcde\0" -> 这样的2个连续字符串,传到某个函数里面以后,想简化成
//
// *(a[2])
// a[0] -> 直接访问abc\0
// a[1] -> 直接访问bcde\0
//
// 或者
//
// "abc","bcde" -> 这样的2个连续字符数组,传到某个函数里面以后,想简化成
//
// *(a[2])
// a[0] -> 直接访问abc
// a[1] -> 直接访问bcde
#include <stdio.h>
#include <string.h>
char s1[]="abc\0bcde";
char *s2[2]={"abc","bcde"};
void func1(void *p) {
char *a[2];
a[0]=(char *)p;
a[1]=(char *)p+strlen((char *)p)+1;
printf("func1\n");
printf("a[0]==[%s],a[1]==[%s]\n",a[0],a[1]);
}
void func2(void *p) {
char *a[2];
a[0]=((char **)p)[0];
a[1]=((char **)p)[1];
printf("func2\n");
printf("a[0]==[%s],a[1]==[%s]\n",a[0],a[1]);
}
int main() {
func1(s1);
func2(s2);
return 0;
}
//func1
//a[0]==[abc],a[1]==[bcde]
//func2
//a[0]==[abc],a[1]==[bcde]