c语言指针GetMemory经典例子
C语言:二级指针的作用

C语⾔:⼆级指针的作⽤⼆级指针的作⽤⽤处特别⼤⾸先主要在数据结构之中当改变指针的时候就需要通过改变指针的指针的值来改变!在数据结构中⽤处很⼴.最普遍的⽐如说链表,通过调⽤函数改变了链表中的元素,那么整个链表就发⽣了变化,这种情况下就会⽤到⼆级指针,因为链表的起始是通过指向头结点的指针来执⾏的,所以必须要改变这个指针,怎么样使⼀个指针改变?在形参传递时,必须传递指针的地址,也就是指向指针的指针.指向指针的指针的作⽤ :当要修改实参指针的指向的时候,形参必须使⽤指向指针的指针。
当修改的是实参指针指向的内容时,则形参只需是指针即可以下是经典程序(载⾃林锐的从c\c++⾼质量编程),讲解的部分是我个⼈理解void GetMemory(char *p,int num){p=(char*)malloc(sizeof(char)*num); //p是形参指向的地址}void main(){char *str=NULL;GetMemory(str,100); //str是实参指向的地址,不能通过调⽤函数来申请内存strcpy(str,"hello");}结构是编译能通过,却不能运⾏,为什么呢?先说⼀下指针作为函数参数的意义:当将指针作为参数时,实参向形参传递的是地址,在函数执⾏过程中,既可以对该参数指针进⾏处理,也可以对该参数指针所指向的数据进⾏处理,(以上程序段来说就是可以对p或*p进⾏处理)。
由于此时形参和实参都是指向同⼀个存储单元,因此当形参指针所指向的数据改变时,实参指针所指向的数据也作相应的改变,因此这时的形参可以作为输出参数使⽤。
(str和p应同时更改!)按照上⾯的说法,这个程序应该没有问题的啊,实参str和形参p指向同⼀个存储单元,给形参分配的内存单元应该也给实参分配了才对啊,问题就是在这⾥实参和形参是指向同⼀个地址,它们只是指向相同,但它们⾃⾝的地址不是同时申请的,就是说p在申请内存时,相当于是把p的指向给改了,但是str的指向仍然没有改!所以尽管str调⽤了GetMemory,但它仍然是个空指针,所以进⾏strcpy是就不能运⾏。
C语言数组参数与指针参数

C语言数组参数与指针参数我们都知道参数分为形参和实参。
形参是指声明或定义函数时的参数,而实参是在调用函数时主调函数传递过来的实际值。
一、一维数组参数1、能否向函数传递一个数组?看例子:void fun(char a[10]){char c = a[3];}intmain(){char b[10] = “abcdefg”;fun(b[10]);return 0;}先看上面的调用,fun(b[10]);将b[10]这个数组传递到fun 函数。
但这样正确吗?b[10]是代表一个数组吗?显然不是,我们知道b[0]代表是数组的一个元素,那b[10]又何尝不是呢?只不过这里数组越界了,这个b[10]并不存在。
但在编译阶段,编译器并不会真正计算b[10]的地址并取值,所以在编译的时候编译器并不认为这样有错误。
虽然没有错误,但是编译器仍然给出了两个警告:warning C4047: 'function' : 'char *' differs in levels of indirection from 'char 'warning C4024: 'fun' : different types for formal and actual parameter 1这是什么意思呢?这两个警告告诉我们,函数参数需要的是一个char*类型的参数,而实际参数为char 类型,不匹配。
虽然编译器没有给出错误,但是这样运行肯定会有问题。
如图:这是一个内存异常,我们分析分析其原因。
其实这里至少有两个严重的错误。
第一:b[10]并不存在,在编译的时候由于没有去实际地址取值,所以没有出错,但是在运行时,将计算b[10]的实际地址,并且取值。
这时候发生越界错误。
第二:编译器的警告已经告诉我们编译器需要的是一个char*类型的参数,而传递过去的是一个char 类型的参数,这时候fun 函数会将传入的char 类型的数据当地址处理,同样会发生错误。
C语言技术的高级用法——进阶开发技巧详解

C语言技术的高级用法——进阶开发技巧详解C语言作为一门广泛应用于嵌入式系统和底层软件开发的编程语言,其高级用法和进阶开发技巧对于程序员来说至关重要。
本文将详细介绍一些C语言的高级用法和进阶开发技巧,帮助读者更好地掌握和应用C语言。
一、指针的高级应用指针是C语言中的重要概念,利用指针可以实现更高效的内存管理和数据操作。
以下是一些常见的指针高级应用:1. 指针的指针指针的指针是指一个指针变量指向另一个指针变量的地址。
通过使用指针的指针,可以实现对指针变量的动态修改和访问,进一步提高程序的灵活性。
2. 函数指针函数指针可以指向程序中的函数,通过函数指针可以实现对函数的动态调用和替代。
这在实现回调函数和函数式编程时非常有用。
3. 指针与数组指针和数组之间有着密切的关系,可以通过指针来遍历和操作数组元素,这样可以减少内存的占用和提高程序的运行效率。
二、内存管理与优化技巧C语言需要手动管理内存,合理地进行内存管理和优化可以提高程序的性能和稳定性。
以下是一些常用的内存管理和优化技巧:1. 内存分配和释放C语言提供了malloc()和free()函数用于动态分配和释放内存。
合理使用这些函数可以减少内存的浪费和泄漏。
2. 内存对齐内存对齐可以提高内存访问的效率,尤其对于嵌入式系统来说更为重要。
通过使用内存对齐的技巧,可以减少内存读取的时间,提高程序的运行效率。
3. 缓存优化程序中的缓存访问对于性能有着重要影响。
通过充分利用缓存的特性,如空间局部性和时间局部性,可以减少缓存的命中不中和提高程序的效率。
三、并发编程与多线程随着多核处理器的普及,多线程编程成为了提高程序性能的重要方式。
C语言提供了一些库和技术用于并发编程和多线程的实现。
1. 线程创建与管理C语言的线程库提供了线程的创建和管理方法,可以创建多个线程来执行不同的任务,提高程序的并行性。
2. 互斥与同步多线程访问共享资源时需要进行同步和互斥操作以避免竞态条件的发生。
常见C语言笔试题

五、编写strcpy函数(10分)已知strcpy函数的原型是char *strcpy(char *strDest, const char *strSrc);其中strDest是目的字符串,strSrc是源字符串。
(1)不调用C++/C的字符串库函数,请编写函数strcpychar *strcpy(char *strDest, const char *strSrc);{assert((strDest!=NULL) && (strSrc !=NULL)); // 2分char *address = strDest; // 2分while( (*strDest++ = * strSrc++) != ‘\0’ ) // 2分NULL ;return address ; // 2分}(2)strcpy能把strSrc的内容复制到strDest,为什么还要char * 类型的返回值?答:为了实现链式表达式。
// 2分例如int length = strlen( strcpy( strDest, “hello world”) );六、编写类String的构造函数、析构函数和赋值函数(25分)已知类String的原型为:class String{public:String(const char *str = NULL); // 普通构造函数String(const String &other); // 拷贝构造函数~ String(void); // 析构函数String & operate =(const String &other); // 赋值函数private:char *m_data; // 用于保存字符串};请编写String的上述4个函数。
标准答案:// String的析构函数String::~String(void) // 3分{delete [] m_data;// 由于m_data是内部数据类型,也可以写成delete m_data; }// String的普通构造函数String::String(const char *str) // 6分{if(str==NULL){m_data = new char[1]; // 若能加NULL 判断则更好*m_data = …\0‟;}else{int length = strlen(str);m_data = new char[length+1]; // 若能加NULL 判断则更好strcpy(m_data, str);}}// 拷贝构造函数String::String(const String &other) // 3分{int length = strlen(other.m_data);m_data = new char[length+1]; // 若能加NULL 判断则更好strcpy(m_data, other.m_data);}// 赋值函数String & String::operate =(const String &other) // 13分{// (1) 检查自赋值// 4分if(this == &other)return *this;// (2) 释放原有的内存资源// 3分delete [] m_data;// (3)分配新的内存资源,并复制内容// 3分int length = strlen(other.m_data);m_data = new char[length+1]; // 若能加NULL 判断则更好strcpy(m_data, other.m_data);// (4)返回本对象的引用 // 3分return *this;}华为笔试2006-2-28 星期二(Tuesday) 晴1、局部变量能否和全局变量重名?答:局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。
华三笔试题

H3C华三技术有限公司[笔试题]2013-09-25注:笔试题根据面试者回忆记录,仅供参考;以下题目都是在小端结尾的32位x86 CPU上面运行的代码:一.编程题1. 请实现一个函数,对于给定的整型参数N,该函数能够打印出自然数中的头N 个质数(15分)。
#include <stdio.h>#define N 10000void find_zs(int num){int i;int j;printf("%d以前的质数是:",num);for (i=2;i<num;i++){for (j=2;j<i;j++){if (0 == i%j){break;}if (i-1 == j){printf("%d ",i);}}}}int main(){find_zs(N);return 0;}2.链表节点结构体定义struct node{int data;struct node *prev;struct node *next;}假设已经构建完毕的一个双向链表有节点A-B-C-D-E-F,从中截断,以C为截断点,传入节点C的指针,截断后重新连接的链表变为C-D-E-F-A-B的形式,写出实现这一功能的C语言代码,返回新链表的头节点指针。
(10分)#include <stdio.h>#include <stdlib.h>struct node{int data;struct node *prev;struct node *next;};int main(){//形成A-B-C-D-E-F的双向链表用1-2-3-4-5-6来表示int i;node * head = (node *)malloc(sizeof(node));head->data = 1;head->next = NULL;head->prev = NULL;node * p = head;node * q = head;for (i=0;i<5;i++){q = (node *)malloc(sizeof(node));q->data = i + 2;p->next = q;q->prev = p;q->next = NULL;p = q;}//打印链表中的data,确认双向链表生成p = head;q = head;for (i=0;i<6;i++){printf("%d-",p->data);q = p->next;p = q;}printf("\n");//找到C(3)节点,并把指针放到tmp_head,同时把p,q指向链表尾p = head;q = head;node * tmp_head = head;while(NULL != p->next){if (3 == p->data){tmp_head = p;}q = p->next;p = q;}//把A-B节点挪到F节点后面p->next = head;head->prev = p;q = head->next;q->next = NULL;//打印当前链表,验证结果是否正确p = tmp_head;q = tmp_head;for(i=0;i<6;i++){printf("%d-",p->data);q = p->next;p = q;}printf("\n");return 0;}二.问答题(每题4分)1.请写出float x 与“零值”比较的if 语句:#define EPSINON 1e-6if(x<= EPSINON && x>=- EPSINON)2. 用预处理指令#define声明一个常数,用来表示一年有多少秒(忽略闰年问题) #define N (365*24*3600)ul3. void GetMemory(char *p){p = (char *)malloc(100);}void Test(void){char *str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);}请问运行Test函数会有什么样的结果?程序崩溃这其实是一个参数传递的问题.修改变量值需要传递该变量类型的一级指针;修改一级指针指需要传递对应类型的二级指针./view/948185300b4c2e3f572763a1.html 4. char *GetMemory(void){char p[] = "hello world";return p;}void Test(void){char *str = NULL;str = GetMemory();printf(str);}请问运行Test函数会有什么样的结果程序执行后结果未知,可能是hell。
C语言内存分配问题(整理)

我查了下资料,有说分四个,有说分五个加一个程序代码区,我没查到参考的专业书籍。所 以麻烦知道的告知一下,完善一下。
2、 内存分配方式 内存分配方式有三种:
1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整 个运行期间都存在。例如全局变量,static 变量。
4、动态分配释放内存举例 用 malloc 动态分配内存后一定要判断一下分配是否成功,判断指针的值是否为 NULL。 内存分配成功后要对内存单元进行初始化。 内存分配成功且初始化后使用时别越界了。 内存使用完后要用 free(p)释放,注意,释放后,p 的值是不会变的,仍然是一个地址值, 仍然指向那块内存区,只是这块内存区的值变成垃圾了。为了防止后面继续使用这块内存, 应在 free(p)后,立即 p=NULL,这样后面如果要使用,判断 p 是否为 NULL 时就会判断出 来。
NO.2
char *GetMemory(void) {
char Байду номын сангаас[] = hello world; retrun p; } void Test(void) { char *str = NULL; str = GetMemory(); printf(str); }
问题同 NO.1
NO.3
void GetMemory(char **p, int num) {
free(str); if(str != NULL) {
strcpy(str,"world"); printf(str); } }
问题同 NO.1 我对以上问题的分析:
NO.1:程序首先申请一个 char 类型的指针 str,并把 str 指向 NULL(即 str 里存的是 NULL 的地址,*str 为 NULL 中的值为0),调用函数的过程中做了如下动作: 1、申请一个 char 类型的指针 p, 2、把 str 的内容 copy 到了 p 里(这是参数传递过程中系统所做的), 3、为 p 指针申请了 100 个空间, 4、返回 Test 函数.最后程序把字符串 hello world 拷贝到 str 指向的内存空间里.到这里错 误出现了! str 的空间始终为 NULL 而并没有实际的空间.深刻理解函数调用的第 2 步,将不难发现问 题所在!(注意:传递的参数和消除的参数) NO.2:程序首先申请一个 char 类型的指针 str,并把 str 指向 NULL.调用函数的过程中做了 如下动作: 1申请一数组 p[]并将其赋值为 hello world(数组的空间大小为 12), 2返回数组名 p 付给 str 指针(即返回了数组的首地址). 那么这样就可以打印出字符串"hello world"了么?当然是不能的! 因为在函数调用的时候漏掉了最后一步.也就是在第2步 return 数组名后,函数调用还要 进行一步操作,也就是释放内存空间.当一个函数被调用结束后它会释放掉它里面所有的变 量所占用的空间.所以数组空间被释放掉了,也就是说 str 所指向的内容将不确定是什么东 西. NO.3:正确答案为可以打印出 hello.但内存泄漏了! 需要用 free()函数进行释放。
c语言面试题__指针篇

c语言面试题__指针篇c语言面试题__指针篇1. char * const p;char const * pconst char *p上述三个有什么区别?char * const p; //常量指针,p的值不可以修改char const * p;//指向常量的指针,指向的常量值不可以改const char *p; //和char const *p------------------------------------------------------2. char str1[] = "abc";char str2[] = "abc";const char str3[] = "abc";const char str4[] = "abc";const char *str5 = "abc";const char *str6 = "abc";char *str7 = "abc";char *str8 = "abc";cout << ( str1 == str2 ) << endl;cout << ( str3 == str4 ) << endl;cout << ( str5 == str6 ) << endl;cout << ( str7 == str8 ) << endl;打印结果是什么?解答:结果是:0 0 1 1str1,str2,str3,str4是数组变量,它们有各自的内存空间;而str5,str6,str7,str8是指针,它们指向相同的常量区域-----------------------------------------------3. 以下代码中的两个sizeof用法有问题吗?void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母{for( size_t i=0; i<="str[i]" )="" )<="" ++i="" if(="" p="" sizeof(str[0]);="" str[i]<="z">str[i] -= ('a'-'A' );}char str[] = "aBcDe";cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;UpperCase( str );cout << str << endl;答:函数内的sizeof有问题。
c语言经典笔试题(非常全)

1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL2. 写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个。
#define MIN(A,B) ((A) <= (B) (A) : (B))4. 嵌入式系统中经常要用到无限循环,你怎么样用C编写死循环呢?这个问题用几个解决方案。
我首选的方案是:while(1){}一些程序员更喜欢如下方案:for(;;){}第三个方案是用gotoLoop:...goto Loop;5. 用变量a给出下面的定义a) 一个整型数(An integer)b) 一个指向整型数的指针(A pointer to an integer)c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)d) 一个有10个整型数的数组(An array of 10 integers)e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数(An array of ten pointers to functions that take an integer argument and return an integer )答案是:a) int a; // An integerb) int *a; // A pointer to an integerc) int **a; // A pointer to a pointer to an integerd) int a[10]; // An array of 10 integerse) int *a[10]; // An array of 10 pointers to integersf) int (*a)[10]; // A pointer to an array of 10 integersg) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integerh) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer6. 关键字static的作用是什么?这个简单的问题很少有人能回答完全。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
GetMemory的典型例子2010-01-13 18:24 520人阅读评论(2) 收藏举报//NO.1:程序首先申请一个char类型的指针str,并把str指向NULL(即str里存的是NULL的地址,*str为NULL中的值为0),调用函数的过程中做了如下动作:1申请一个char 类型的指针p,2把str的内容copy到了p里(这是参数传递过程中系统所做的),3为p指针申请了100个空间,4返回Test函数.最后程序把字符串hello world拷贝到str 指向的内存空间里.到这里错误出现了!str的空间始终为NULL而并没有实际的空间.深刻理解函数调用的第2步,将不难发现问题所在!void GetMemory(char *p){p = (char*)malloc(100);}void Test(void){char *str = NULL;GetMemory(str);strcpy(str, "hello world");printf(str);}//请问运行Test函数后会是什么样的结果?//NO.2:程序首先申请一个char类型的指针str,并把str指向NULL.调用函数的过程中做了如下动作:1申请一数组p[]并将其赋值为hello world(数组的空间大小为12),2返回数组名p付给str指针(即返回了数组的首地址).那么这样就可以打印出字符串"hello world"了么?当然是不能的!因为在函数调用的时候漏掉了最后一步.也就是在第2步return数组名后,函数调用还要进行一步操作,也就是释放内存空间.当一个函数被调用结束后它会释放掉它里面所有的变量所占用的空间.所以数组空间被释放掉了,也就是说str所指向的内容将不确定是什么东西.char *GetMemory(void){char p[] = "hello world";return p;void Test(void){char *str = NULL;str = GetMemory();printf(str);}//NO.3:问题同NO.1,正确答案为可以打印出hello.但内存泄漏了!void GetMemory(char **p, int num){*p = (char*)malloc(num);}void Test(void){char *str = NULL;GetMemory(&str, 100);strcpy(str, "hello");printf(str);}//NO.4:申请空间,拷贝字符串,释放空间.前三步操作都没有任何问题.到if语句里的判断条件开始出错了,因为一个指针被释放之后其内容并不是NULL,而是一个不确定的值.所以if语句永远都不能被执行.这也是著名的"野"指针问题.所以我们在编写程序释放一个指针之后一定要人为的将指针付成NULL.这样就会避免出现"野"指针的出现.有人说"野"指针很可怕,会带来意想不到的错误.void Test(void){char *str = (char*)malloc(100);strcpy(str, "hello");free(str);if (str != NULL)strcpy(str, "world");printf(str);}}void GetMemory1(char *p) {p = (char *)malloc(100); }void Test1(void){char *str = NULL;GetMemory1(str);strcpy(str, "hello world");printf(str);}//str一直是空,程序崩溃char *GetMemory2(void) {char p[] = "hello world";return p;}void Test2(void){char *str = NULL;str = GetMemory2();printf(str);}char *GetMemory3(void)return "hello world";}void Test3(void){char *str = NULL;str = GetMemory3();printf(str);}//Test3 中打印hello world,因为返回常量区,而且并没有被修改过。
Test2中不一定能打印出hello world,因为指向的是栈。
void GetMemory4(char **p, int num){*p = (char *)malloc(num);}void Test4(void){char *str = NULL;GetMemory3(&str, 100);strcpy(str, "hello");printf(str);}//内存没释放void Test5(void){char *str = (char *) malloc(100);strcpy(str, "hello");free(str);if(str != NULL)strcpy(str, "world");printf(str);}}//str为野指针,打印的结果不得而知void Test6(){char *str=(char *)malloc(100);strcpy(str, "hello");str+=6;free(str);if(str!=NULL){strcpy(str, "world");printf(str);}}//VC断言失败,运行错误另转一则:char *GetMemory3(int num){char *p = (char *)malloc (sizeof(char) * num); return p; //返回指针 p}void Test3(void){char *str = NULL;str = GetMemory3(100); //这里指针 str也和指针 p的指向一样的内存块。
strcpy(str, "hello");cout<< str << endl;free(str); //这里最终只是释放了str指向的内存块,对于str指针依然还是指向那块内存,看了一些资料说应该加一句str=0;那指针 p呢?p也依然在指向那块内存啊。
}回复:答者:wutaozhao() 信誉:100 级别:user2 日期:2007-6-29 21:42:21 id:41451636指针之间传递的就是地址,所以str和p所指向的内存块是同一个,释放其中任何一个即可答者:what_a_big() 信誉:100 级别:user1 日期:2007-6-29 21:42:21 id:41451637那指针 p呢?=================================================================== ==========after returning from GetMemory()p (局部变量)没了,那块内存还在。
现在str 指向那块内存。
看了一些资料说应该加一句str=0=================================也可以不写str=NULL,只要你不再引用str。
答者:believefym(feng) 信誉:100 级别:user5 日期:2007-6-29 21:50:38 id:41451675同一块内存,释放一次即可,只不过所有指向那块内存的指针都失效了,就像楼主代码里的p和str释放之后str就变成了野指针,加str=NULL,可以避免之后错误使用该指针,方便调试答者:lightnut() 信誉:100 级别:star1 日期:2007-6-29 22:05:48 id:414517361.函数进入Test3():char* str = NULL;======================变量变量的地址变量的值(内容)str 0x0013fe8c 02.str = GetMemory3(..)=====>char *p = (char *)malloc (sizeof(char) * num);将分配的内存起始地址(0x003a60b0)赋给栈变量p,===============================================变量变量的地址变量的值(内容)p 0x0013fda8 0x003a60b03. 从GetMemory3(..)返回, p的值(0x003a60b0)拷贝给str, 栈变量p生命结束, 释放其所占栈内存(地址0x0013fda8)=================================================变量变量的地址变量的值(内容)str 0x0013fe8c 0x003a60b04. free(str): 释放str指向的内存(0x003a60b0开始的内存空间)5. 推出Test3()后, 栈变量str生命结束, 释放其所占栈内存(地址0x0013fe8c)答者:freshui(五月的风-最近老犯困) 信誉:100 级别:user1 日期:2007-6-29 22:12:07 id:41451763呵呵 p没了已经死了:)注意看变量的作用域答者:buhaohaoxuexi() 信誉:100 级别:user1 日期:2007-6-29 22:37:00 id:41451888为什么会死呢,不是说动态分配是分配在堆上的吗?他不应该死啊。
答者:yydrewdrew(满堂花醉三千客,一剑霜寒十四州) 信誉:100 级别:user1 日期:2007-6-29 23:55:01 id:41452325char *GetMemory3(int num){char *p = (char *)malloc (sizeof(char) * num);return p; //返回指针 p}void Test3(void){char *str = NULL;str = GetMemory3(100); //调用完后p被析构,p为局部作用域存在于函数GetMemory3的栈中,当GetMemory3被调用完后,栈空间被释放,因而被析构。
strcpy(str, "hello");cout<< str << endl;free(str); //这里最好加一句str = NULL。