- 全局变量和局部变量在内存中是否有区别?如果有,是什么区别?
全局变量储存在静态数据库,局部变量在堆栈
- 堆栈溢出一般是由什么原因导致的?
没有回收垃圾资源
- 局部变量能否和全局变量重名?
能,局部会屏蔽全局。 在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。 对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量, 比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内
- 如何引用一个已经定义过的全局变量?
extern 关键字
- 全局变量可不可以定义在可被多个.C文件包含的头文件中?为什么?
可以,在不同的C文件中以static形式来声明同名全局变量。 可以在不同的C文件中声明同名的全局变量,前提是其中只能有一个C文件中对此变量赋初值,此时连接不会出错
内存对齐问题
6. 设有以下说明和定义:(注意变量占用字节在不同平台下是不同的)
typedef union { long i; int k[5]; char c; } DATE; struct data { int cat; DATE cow; double dog; } too; DATE max;
则语句 printf("%d",sizeof(struct date)+sizeof(max));的执行结果是:52
DATE是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20
data是一个struct, 每个变量分开占用空间. 依次为int4 + DATE20 + double8 = 32.
所以结果是 20 + 32 = 52.
当然…在某些16位编辑器下, int可能是2字节,那么结果是 int2 + DATE10 + double8 = 20
- 写出下列代码的输出内容(考察指针函数的用法)
#include<stdio.h> int inc(int a) { return(++a); } int multi(int*a,int*b,int*c) { return(*c=*a**b); } typedef int(*FUNC1)(int); typedef int(*FUNC2)(int*,int*,int*); void show(FUNC2 fun,int arg1, int*arg2) { FUNC1 p=&inc; // 这里用&inc与inc都可以,都是取地址 int temp =p(arg1); fun(&temp,&arg1, arg2); printf("%d\n",*arg2); } main() { int a; show(multi,10,&a); return 0; }
110
- 请找出下面代码中的所有错误
说明:以下代码是把一个字符串倒序,如“abcd”倒序后变为“dcba”
#include"string.h" main() { char*src="hello,world"; char* dest=NULL; int len=strlen(src); dest=(char*)malloc(len); char* d=dest; char* s=src[len]; while(len--!=0) d++=s--; printf("%s",dest); return 0; }
答:
方法1:
int main(){ char* src = "hello,world"; int len = strlen(src); char* dest = (char*)malloc(len+1);//要为/0分配一个空间 char* d = dest; char* s = &src[len-1];//指向最后一个字符 while( len-- != 0 ) *d++=*s--; *d = 0;//尾部要加/0 printf("%s/n",dest); free(dest);// 使用完,应当释放空间,以免造成内存汇泄露 return 0; }
方法2:
#include <stdio.h> #include <string.h> main() { char str[]="hello,world"; int len=strlen(str); char t; for(int i=0; i<len/2; i++) { t=str[i]; str[i]=str[len-i-1]; str[len-i-1]=t; } printf("%s",str); return 0; }
- 用两个栈实现一个队列的功能?要求给出算法和思路!
- 对于一个频繁使用的短小函数,在C语言中应用什么实现,在C++中应用什么实现?
inline - 代码输出什么?
unsigned char *p1; unsigned long *p2; p1=(unsigned char *)0x801000; p2=(unsigned long *)0x810000; 请问p1+5= ; p2+5= ;
p1+5= 0x801005 ;
p2+5= 0x801014 ;(long型在32位编译器里为4byte,这里0x14=20)
- C/C++编译器中虚表是如何完成的?
14. 内存四区问题
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 1
解答:str1,str2,str3,str4是数组变量,它们有各自的内存空间;
而str5,str6,str7,str8是指针,它们指向相同的常量区域。
- 以下代码中的两个sizeof用法有问题吗?
void UpperCase( char str[] ) // 将 str 中的小写字母转换成大写字母 { for( size_t i=0; i<sizeof(str)/sizeof(str[0]); ++i ) if( 'a'<=str[i] && str[i]<='z' ) str[i] -= ('a'-'A' ); }
这个sizeof是有问题的,数组传参不能只传首地址,还有传数组大小。
char str[] = {1,2,3,4}; printf("%d\n", sizeof(str)/sizeof(str[0])); //4 printf("%d\n", sizeof(str)); //4 int str[] = {1,2,3,4}; printf("%d\n", sizeof(str)/sizeof(str[0])); //4 printf("%d\n", sizeof(str)); //16
- 一个32位的机器,该机器的指针是多少位
指针是多少位只要看地址总线的位数就行了。80386以后的机子都是32的数据总线。所以指针的位数就是4个字节了。 - 代码输出什么?
main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); printf("%d,%d",*(a+1),*(ptr-1)); }
输出:2,5
(a+1)就是a[1],(ptr-1)就是a[4],执行结果是2,5
&a+1不是首地址+1,系统会认为加一个a数组的偏移,是偏移了一个数组的大小(本例是5个int)
int ptr=(int )(&a+1);
则ptr实际是&(a[5]),也就是a+5
原因如下:
&a是数组指针,其类型为 int ()[5];
而指针加1要根据指针类型加上一定的值,
不同类型的指针+1之后增加的大小不同
a是长度为5的int数组指针,所以要加 5sizeof(int)
所以ptr实际是a[5]
但是prt与(&a+1)类型是不一样的(这点很重要)
所以prt-1只会减去sizeof(int*)
a,&a的地址是一样的,但意思不一样,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5].
- 请问以下代码有什么问题:
int main() { char a; char *str=&a; strcpy(str,"hello"); printf(str); return 0; }
没有为str分配内存空间,将会发生异常
问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。
- 用宏定义写出swap(x,y)
#define swap(x, y) (x = x + y;y = x - y; x = x - y;)
- 数组a[N],存放了1至N-1个数,其中某个数重复一次。写一个函数,找出被重复的数字.时间复杂度必须为o(N)函数原型:int do_dup(int a[],int N)
- 什么是预编译 何时需要预编译:
char * const p; char const * p const char *p
上述三个有什么区别?
char * const p; //常量指针,p的值不可以修改
char const * p;//指向常量的指针,指向的常量值不可以改
const char *p; //和char const *p
- 请问以下代码有什么问题:
int main() { char a; char *str=&a; strcpy(str,"hello"); printf(str); return 0; }
没有为str分配内存空间,将会发生异常
问题出在将一个字符串复制进一个字符变量指针所指地址。虽然可以正确输出结果,但因为越界进行内在读写而导致程序崩溃。
- int (*s[10])(int) 表示的是什么?
int (*s[10])(int) 函数指针数组,每个指针指向一个int func(int param)的函数。 - 有以下表达式:
int a=248; b=4;int const c=21;const int *d=&a;
int *const e=&b;int const *f const =&a;
请问下列表达式哪些会被编译器禁止?为什么?
*c=32;d=&b;*d=43;e=34;e=&a;f=0x321f;
*c 这是个什么东东,禁止
*d 说了是const, 禁止
e = &a 说了是const 禁止
const *f const =&a; 禁止 - 交换两个变量的值,不使用第三个变量。即a=3,b=5,交换之后a=5,b=3;
有两种解法, 一种用算术算法, 一种用^(异或)
a = a + b;
b = a - b;
a = a - b;
or
a = a^b;// 只能对int,char…
b = a^b;
a = a^b;
or
a ^= b ^= a; - c和c++中的struct有什么不同?
c和c++中struct的主要区别是c中的struct不可以含有成员函数,而c++中的struct可以。c++中struct和class的主要区别在于默认的存取权限不同,struct默认为public,而class默认为private - 下面代码有什么问题
#include <stdio.h> #include <stdlib.h> void getmemory(char *p) { p=(char *) malloc(100); strcpy(p,"hello world"); } int main( ) { char *str=NULL; getmemory(str); printf("%s/n",str); free(str); return 0; }
程序崩溃,getmemory中的malloc 不能返回动态内存, free()对str操作很危险
- 下面代码有什么问题
char szstr[10]; strcpy(szstr,"0123456789"); 产生什么结果?为什么? 长度不一样,会造成非法的操作,破坏其他内存区的数据
(void )ptr 和 ((void**))ptr的结果是否相同?其中ptr为同一个指针
.(void )ptr 和 ((void**))ptr值是相同的
- 问函数既然不会被其它函数调用,为什么要返回1?
int main() { int x=3; printf("%d",x); return 1; }
mian中,c标准认为0表示成功,非0表示错误。具体的值是某中具体出错信息
- 要对绝对地址0x100000赋值,我们可以用
(unsigned int*)0x100000 = 1234;
那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?
((void ()( ))0x100000 ) ( );
首先要将0x100000强制转换成函数指针,即:
(void ()())0x100000
然后再调用它:
((void ()())0x100000)();
用typedef可以看得更直观些:
typedef void()() voidFuncPtr;
*((voidFuncPtr)0x100000)(); - 已知一个数组table,用一个宏定义,求出数据的元素个数
#define NTBL #define NTBL (sizeof(table)/sizeof(table[0]))
- 输出多少?并分析过程
unsigned short A = 10; printf("~A = %u/n", ~A); char c=128; printf("c=%d/n",c);
第一题,~A =0xfffffff5,int值 为-11,但输出的是uint。所以输出4294967285
第二题,c=0x10,输出的是int,最高位为1,是负数,所以它的值就是0x00的补码就是128,所以输出-128。
这两道题都是在考察二进制向int或uint转换时的最高位处理。
- 分析下面的程序:
void GetMemory(char **p,int num) { *p=(char *)malloc(num); } int main() { char *str=NULL; GetMemory(&str,100); strcpy(str,"hello"); free(str); if(str!=NULL) { strcpy(str,"world"); } printf("/n str is %s",str); getchar(); }
问输出结果是什么?输出str is world。
free 只是释放的str指向的内存空间,它本身的值还是存在的.
所以free之后,有一个好的习惯就是将str=NULL.
此时str指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储空间是可能被重新分配给其他变量的,
尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出world来。
这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。
当你malloc一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),然后在这块空间中记录一些管理信息(一般是在你申请的内存前面一点),并将可用内存的地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继续访问这块地址的,只不过。。。。。。。。楼上都说过了,最好别这么干。
- char a[10],strlen(a)为什么等于15?运行的结果
#include "stdio.h" #include "string.h" void main() { char aa[10]; printf("%d",strlen(aa)); }
sizeof()和初不初始化,没有关系;
strlen()和初始化有关。
char (*str)[20];/str是一个数组指针,即指向数组的指针./
char *str[20];/str是一个指针数组,其元素为指针型数据./
- 代码输出什么?
#include <iostream.h> #include <string.h> #include <malloc.h> #include <stdio.h> #include <stdlib.h> #include <memory.h> typedef struct AA { int b1:5; int b2:2; }AA; void main() { AA aa; char cc[100]; strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz"); memcpy(&aa,cc,sizeof(AA)); cout << aa.b1 <<endl; cout << aa.b2 <<endl; }
答案是 -16和1
首先sizeof(AA)的大小为4,b1和b2分别占5bit和2bit.
经过strcpy和memcpy后,aa的4个字节所存放的值是:
0,1,2,3的ASC码,即00110000,00110001,00110010,00110011
所以,最后一步:显示的是这4个字节的前5位,和之后的2位
分别为:10000,和01
因为int是有正负之分 所以:答案是-16和1
- 求函数返回值,输入x=9999;
int func ( x ) { int countx = 0; while ( x ) { countx ++; x = x&(x-1); } return countx; }
结果呢?
知道了这是统计9999的二进制数值中有多少个1的函数,且有
9999=9×1024+512+256+15
9×1024中含有1的个数为2;
512中含有1的个数为1;
256中含有1的个数为1;
15中含有1的个数为4;
故共有1的个数为8,结果为8。
1000 - 1 = 0111,正好是原数取反。这就是原理。
用这种方法来求1的个数是很效率很高的。
不必去一个一个地移位。循环次数最少。
- 改错:
#include <stdio.h> int main(void) { int **p; int arr[100]; p = &arr; return 0; }
解答:
搞错了,是指针类型不同,
int **p; //二级指针
&arr; //得到的是指向第一维为100的数组的指针
修改如下:
#include <stdio.h> int main(void) { int **p, *q; int arr[100]; q = arr; p = &q; return 0; }
- 下面这个程序执行后会有什么错误或者效果:
#define MAX 255 int main() { unsigned char A[MAX],i;//i被定义为unsigned char for (i=0;i<=MAX;i++) A[i]=i; }
解答:死循环加数组越界访问(C/C++不进行数组越界检查)
MAX=255
数组A的下标范围为:0…MAX-1,这是其一…
其二.当i循环到255时,循环内执行:
A[255]=255;
这句本身没有问题…但是返回for (i=0;i<=MAX;i++)语句时,
由于unsigned char的取值范围在(0…255),i++以后i又为0了…无限循环下去.
- A.c 和B.c两个c文件中使用了两个相同名字的static变量,编译的时候会不会有问题?这两个static变量会保存到哪里(栈还是堆或者其他的)?
static的全局变量,表明这个变量仅在本模块中有意义,不会影响其他模块。
他们都放在数据区,但是编译器对他们的命名是不同的。
如果要使变量在其他模块也有意义的话,需要使用extern关键字。 - 在对齐为4的情况下
struct BBB { long num; char *name; short int data; char ha; short ba[5]; }*p; p=0x1000000; p+0x200=____; (Ulong)p+0x200=____; (char*)p+0x200=____;
解答:假设在32位CPU上,
sizeof(long) = 4 bytes
sizeof(char *) = 4 bytes
sizeof(short int) = sizeof(short) = 2 bytes
sizeof(char) = 1 bytes
由于是4字节对齐,
sizeof(struct BBB) = sizeof(p)
= 4 + 4 + 2 + 1 + 1/补齐/ + 25 + 2/补齐/ = 24 bytes (经Dev-C++验证)
p=0x1000000;
p+0x200=____;
= 0x1000000 + 0x200*24
(Ulong)p+0x200=____;
= 0x1000000 + 0x200
(char*)p+0x200=____;
= 0x1000000 + 0x200*4
可以参考一下指针运算的细节
- 写一段程序,找出数组中第k大小的数,输出数所在的位置。例如{2,4,3,4,7}中,第一大的数是7,位置在4。第二大、第三大的数都是4,位置在1、3随便输出哪一个均可。函数接口为:int find_orderk(const int* narry,const int n,const int k)
要求算法复杂度不能是O(n^2) - 请问一下程序将输出什么结果?
char *RetMenory(void) { char p[] = “hello world”; return p; } void Test(void) { char *str = NULL; str = RetMemory(); printf(str); }
RetMenory执行完毕,p资源被回收,指向未知地址。返回地址,str的内容应是不可预测的, 打印的应该是str的地址