C语言面试题

1.理解main函数的参数,运行一下看看结果
#include <stdlib.h>


int main(int argc, char* argv[], char *envp[])
{
int i = 0;
// walk through all the arguments
// way 1:
// for (i=0; i<argc; i++)
// {
// printf("argv[%d]=%s\n", i, argv[i]);
// }
// way 2:
for (i=0; argv[i]!=NULL; i++)
{
printf("argv[%d]=%s\n", i, argv[i]);
}


// walk through all the environment variables
for (i=0; envp[i] != NULL; i++)
printf("envp[%d]=%s\n", i, envp[i]);


system("pause");
return 0;
}


1.
地址相减代表元素偏移的个数
#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{


    int s[25];  
    
    printf("%p\n",&s[0]);    
    printf("%p\n",&s[24]);
    
    int * p = &s[0] , * t = &s[24];
    
    printf("%d\n",t-p);   // 24,而不是96


    system("PAUSE");
    return 0;
}


2.
书本问题:
使用printf()语句做下面的练习
A 输出整型变量sum的值
B 输出文本字符串"Welcome",并跟一个新行
C 输出字符变量letter
D 输出浮点类型变量discount
E 输出浮点型变量dump,并保留两个小数位


#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{


int sum = 10;
printf("%d", sum);


printf("%s\n", "Welcome");


char letter = 'C';
printf("%c\n", letter);


float discount = 1.4f;
printf("%f\n", discount);


float dump = 1.456f;
printf("%.2f\n", dump);  //这个我们可能不会
    system("PAUSE");
    return 0;
}


3.
char *p = new char;
*p = 'h';




char *p = new char;
*p = "hello";   // 不能这样干,两个类型都不一样,编译都通不过




2.有如下程序段
  unsigned char *p1;
  unsigned long *p2;


  p1=(unsigned char *)0x801000;
  p2=(unsigned long *)0x810000;


请问  p1+5= 0x801005   // 指针加整数表示偏移多少个指针类型的元素
      p2+5= 0x810014


3.有如下程序段
  unsigned char a[5];
  unsigned char *p,*q;
  a[0]=1;
  a[1]=2;
  a[2]=3;
  a[3]=4;
  a[4]=5;
  p=a;
  q=&a[3];
 
请问a[q-p]= 4   // q-p = 3,当然为4了




在VC中,将struct member alignment设为1 byte,不知是否影响运行速度,为什么默认是8 bytes呢?
答:
因为C++内建类型中,double就是8 bytes,所以按这个东西对齐绝对不会对歪。
例子:
#include <stdio.h>
#include <stdlib.h>


struct test
{
double d;
int i;
};


int main(int argc, char *argv[])
{
printf("%d\n", sizeof(test));   // 默认为16

    system("PAUSE");
    return 0;
}




4.字长对齐带来的效率提升  


经常看到有人问起对齐有什么作用之类问题
因为今天和同事谈到了ARM平台下数据总线宽度及对齐方式对程序效率的影响问题
在定义结构数据类型时,为了提高系统效率,要注意字长对齐原则。
正好有点感触给大家谈谈 本人水平有限的很有什么问题请朋友指正:
本文主要给大家解释下所谓的对齐到底是什么?怎么对齐?为什么会对齐或者说对齐带来什么样的效率差异?


1.
先看下面的例子:
#include <iostream.h>
#pragma pack(4)
struct A
{
char a;
int  b;
};
#pragma pack()


#pragma pack(1)
struct B
{
char a;
int  b;
};
#pragma pack()


int main()



A a;
cout<<sizeof(a);//8
 
B b;
cout<<sizeof(b);//5
}


默认的vc我记得是8字节对齐,ADS下是一字节对齐 
因为是c/c++社区大家对PC比较熟悉 我就谈PC下的对齐
PC下设计放的太长时间的有错误就别客气直接说


大家可以看到在ms的vc下按4字节对齐和1字节对齐的结果是截然不同的分别为8和5
为什么会有这样的结果呢?这就是x86上字节对齐的作用。为了加快程序执行的速度,
一些体系结构以对齐的方式设计,通常以字长作为对齐边界。对于一些结构体变量,
整个结构要对齐在内部成员变量最大的对齐边界,如A,整个结构以4为对齐边界,所以sizeof(a)为8,而不是5。
如果是原始我们概念下的的A中的成员将会一个挨一个存储 应该只有char+int只有5个字节 
这个差异就是由于对齐导致的 
显然我们可以看到 A的对齐要比B浪费3个字节的存储空间 
那为什么还要采取对齐呢? 
那是因为体系结构的对齐和不对齐,是在时间和空间上的一个权衡。
字节对齐节省了时间。应该是设计者考虑用空间换取时间。
为什么说对齐会提高效率呢节省时间?我想大家要理解的重点之重点就在这里了
在我们常用的PC下总线宽度是32位
1.如果是总线宽度对齐的话
那么所有读写操作都是获取一个<=32位数据可以一次保证在数据总线传输完毕
没有任何的额外消耗 
|1|2|3|4|5|6|7|8|
从1开始这里是a的起始位置,5起始为b的位置 访问的时候
如果访问a一次在总线传输8位其他24位无效的
访问b时则一次在总线上传输32完成 
读写均是一次完整 
插叙一下 读操作先要将读地址放到地址总线上然后下个时钟周期再从外部
存储器接口上读回数据通过数据总线返回,需要两个周期 
而写操作一次将地址及数据写入相应总线就完成了 
读操作要比写操作慢一半 
 
2.我们看访问数据时如果不对齐地址的情况 
|1|2|3|4|5|6|7|8|
此时a的地址没变还在1而因为是不对齐则b的位置就在2处 
这时访问就带来效率上问题 访问a时没问题还是读会一个字节
但是2处地址因为不是总线宽度对齐一般的CPU在此地址操作将产生error 
如sparc,MIPS。它们在硬件的设计上就强制性的要求对齐。在不对齐的地址上肯定发生错误
但是x86是支持非对齐访问的 
它通过多次访问来拼接得到的结果,具体做法就是从1地址处先读回后三字节234 暂存起来
然后再由5地址处读回一个字节5 与234进行拼接组成一个完整的int也就是b返回
大家看看如此的操作带来的消耗多了不止三倍很明显在字长对齐时效率要高许多 
淡然这种效率仅仅是访问多字节带来的 如果还是进行的byte操作那效率差不了多少




目前的开发普遍比较重视性能,所以对齐的问题,有2种不同的处理方法: 
1)    有一种使用空间换时间做法是显式的插入reserved成员:
         struct A{
           char a;
           char reserved1[3];//使用空间换时间,呵呵,终于理解H接口协议上为什么保留字段是3个字节了,原来是为了字节对齐,当初幸好没犯啥发傻言
           int b;
            
}a;
2)    随便怎么写,一切交给编译器自动对齐。
还有一种将逻辑相关的数据放在一起定义 


代码中关于对齐的隐患,很多是隐式的。比如在强制类型转换的时候。下面举个例子:
unsigned int i = 0x12345678;
unsigned char *p=NULL;
unsigned short *p1=NULL;


p=&i;
*p=0x00;
p1=(unsigned short *)(p+1);
*p1=0x0000;
最后两句代码,从奇数边界去访问unsignedshort型变量,显然不符合对齐的规定。
在x86上,类似的操作只会影响效率,但是在MIPS或者sparc上,可能就是一个error


例:
#include <stdio.h>
#include <stdlib.h>


int main(int argc, char *argv[])
{
int i;
char c;
int j;
double d;
printf("0x%08X\n", &i);   // 0x0012FF7C
printf("0x%08X\n", &c);   // 0x0012ff78
printf("0x%08X\n", &j);   // 0x0012ff74
printf("0x%08X\n", &d);   // 0x0012ff6C


    system("PAUSE");
    return 0;
}
聂富华:在非结构体中,程序是按4字节对齐的.但是我就想不通,4字节对齐就完全满足需要了,为什么struct默认要8字节对齐?




我补充一句


一般情况下对于字节对齐的问题,有3种处理方法
第一种就是上边的1
第二种,就是用强制对齐,比如vc的 #pragma pack
这样有个缺点,就是不便于移植,因为你写的代码里用了,
如果通信的话,别人那里未必使用了
第三种,统统使用long,这样的话,就不会有字节对齐引发的内存错误了
就是有点浪费,呵呵
 
   
顶一下,顺便吹毛求疵一次:


默认的vc我记得是4字节对齐
------------------------------------------
默认是不确定的,看最大结构成员的长度,如果有double的话可能为8。


另外,x86上非对齐内存访问的主要缺点是取/存数据部分需要的时钟周期增多,指令长度变长,如果只有一条这样的操作的话影响应该还不严重(因为有流水线的存在),多了就慢了。
(寒,昨天我还以为会变成两条指令的说……)


 
========================================================
用long其实会产生更大的问题,必须要考虑到平台的字节顺序问题,用个指针就知道了……


当然,如果仅仅是把long在需要的时候强制转换到char的话是不会有什么问题的……




另外,不对齐似乎会对流水线产生冲击的,并且某些指令的操作数要求16字节对齐,不对齐会产生一般保护错误……
 
   
用long其实会产生更大的问题,必须要考虑到平台的字节顺序问题,用个指针就知道了……
//这个顺序通过芯片的特殊寄存器可以设置 大端还是小端只要不在一次运行中多次设置
//这个我认为还是没有什么问题的 


另外,不对齐似乎会对流水线产生冲击的,并且某些指令的操作数要求16字节对齐,不对齐会产生一般保护错误……
//这个是本身芯片数据存取的特性,有些片子是要求地址对齐 有些是允许不对齐访问的
//对于要求对齐的你的不对齐地址上操作数据就会产生error




6.字符数组问题 ?
这是关于结束符问题,下面的程序结果随机性太强,没有太多意义
没带结束符的字符数组就不能当作字符串处理
#include "stdafx.h"
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void main()
{
    char string[10], str1[10];
char *string2 = "1234567890";
for(int I=0; I<10;I++)
{
        str1[I] ='a';
}
cout<<sizeof(str1)<<endl;   //结果为10
cout<<strlen(str1)<<endl;   //结果为27                       
cout<<str1<<endl;           //aaaaaaaaaa烫烫烫烫烫烫烫!!? 

//strcpy(string, str1);       //这里的strcpy会出错
//cout<<strlen(string)<<endl;
//cout<<string<<endl;

strcpy(string, string2);    //这里的strcpy为什么不会出错?
cout<<strlen(string)<<endl; //10
cout<<sizeof(string)<<endl; //10
cout<<string<<endl;         //1234567890


system("pause");
}


7.
下面为六种,判断各类情况的输出结果,并分析原因:


void GetMemory(char *p)                    //情形一,往NULL地址拷贝,错
{
p = (char*)malloc(100);
}
void Test(void)
{
char *str = NULL;
 
GetMemory(str); 
strcpy(str,"hello,world");
printf(str);
}
char *GetMemory(void)                     //情形二,返回临时对象的地址,错
{
char p[] = "hello world";
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
void Test(void)                           //情形三,越界,错
{
int iLen = 100;
p = (char *)malloc(iLen);
memset(p, 0x00,iLen+100);
}
void GetMemory(char **0, int num)         //情形四,拷贝越界,错
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str,5);
strcpy(str, "hello");
printf(str);
free(str);
}
void GetMemory(char **p, int num)         //情形五,对(已验证)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str,"hello");
printf(str);
}
void Test(void)                            //情形六,往一个释放了的内存拷贝数据,错
{
char *str = (char *)malloc(100);
strcpy(str,"hello");
free(str);
if(str!=NULL){
strcpy(str,"world");
printf(str);
}
}




7.
1. 有双向循环链表结点定义为: (待写)
struct node 
{ int data; 
struct node *front,*next; 
}; 
有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两链表中data值相同的结点删除 


2. 编程实现:找出两个字符串中最大公共子字符串,如"abccade","dgcadde"的最大子串为"cad" (待写)


3. 编程实现:把十进制数(long型)分别以二进制和十六进制形式输出,不能使用printf系列库函数 (待写)




8.
今天参加了慧通在我们学校组织的笔试 题目多 面广 C 数据结构 操作系统 软件工程 数据库各个方面都有 鄙人学电子出身 只知道 C/数据结构 哎 可惨了 答的一塌糊涂 
1.(已验证)
#include <stdio.h>
int main()
{
    int n = 4;
    
    while ( n-- )
          printf("%d", --n);
          
    return 0;
}  的输出结果
答:20


2.switch( c ) c不能为double型数( yes / no)
答: yes (已验证)




9.怎样删除整形数组中相同的数? 如: s[]={1,2,3,4,5,4,6,3,8} 怎样使 s[]={1,2,3,4,5,6,8}
#include "stdlib.h"
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;


int main(int argc, char *argv[]) 
{
int s[]={1,2,3,4,5,4,6,3,8};

vector<int> v,vend;

for(int i=0;i<sizeof(s)/sizeof(s[0]);i++)
{
v.push_back(s[i]);
}

sort(v.begin(),v.end());

for(i=0;i<v.size();i++) 
{
if(vend.size()==0 || vend.back() != v[i]) //如果目的vector中没有元素的话直接放入,否则判断一下是否相等再放入
{
vend.push_back(v[i]);
}
}

for(i=0;i<vend.size();i++) 
{
cout << vend[i] << endl;
}
system("pause");


return 0;
}
(已验证,应该有改进的地方)


10.C语言中如何调用exe文件 


system
或者
_exec函数系列 (可以根据实际情况选择 ~)


11.任意输入7个整数到数组S[ ]中,(可以用赋初值的方法),输入一个关键字的值,实现树查找(需要先建二叉树,并用中序遍历验证其正确性),返回地址。(待写)


12.
1.设计函数 int atoi(char *s) (待写)


2. What do the following declarations mean?
  (1)const int a;
  (2)int const a;
  (3)const int *a;
  (4)int * const a;
  (5)int const * a const;


3.编程 (待写)
  将整数转换成字符串:void itoa(int,char);
  例如itoa(-123,s[])则s=“-123”;


4.10个人分成4组 有几种分法?(程序)(不能重复,如:1,1,1,7=7,1,1,1)(待写)


5.如图: 
     7 8 9 10
     6 1 2 11
     5 4 3 12
    16 15 14 13
    设“1”的坐标为(0,0) “7”的坐标为(-1,-1) 编写一个小程序,使程序做到输入坐标(X,Y)之后显示出相应的数字。(待写)


6.编最优化Bubble(int *pIntArray,int L),要求:交换元素不能用临时变量,如果有序需要最优。(待写)


7.判断是否是回文?(待写)
int Check(int n)
{
   int a,b;
   a = n;
   b = 0;
   while( n != 0 )
   {
        b = b*10+n%10;
        n = n / 10;
    }
    return a == b;
}
 


8.
数据结构高手进!!急~~~~~
这个是我们的实验题目,我写了几个程序,但不是很符合题目的要求,谁能帮我改一下吗?
谢谢了~


平时测验,以下三题任选其一,但分数不一样:(待写)
一.任意输入7个整数到数组s[ ]中(可以用赋初值的方法),输入一个关键字的值,实现顺序查找,返回下标地址。(60分)。
二.意输入7个整数到数组s[ ]中(可以用赋初值的方法),输入一个关键字的值,实现二分查找(需要先排序,排序方法任选),返回下标地址。(80分)。
三.任意输入7个整数到数组s[ ]中(可以用赋初值的方法),输入一个关键字的值,实现树查找(需要先建二叉排序树,并用中序遍历验证其正确性),返回地址。(100分)。


9.
1.编写C程序,要求能读入一正整数n,(n<10),并输出如下图形: (待写)
                 1
                222
               33333
                .
                .
           nn........     nn(共2n-1个n)
                .
                .
              33333
               222
                1


2.编写C程序,要求能读入两个整数m与n,计算并输出m与n的绝对值的最大公约数及最小公倍数. (待写)




11.(已验证)
1,char *p="hello"  //4
2,char p[]="hello" //6
3,void *p=malloc(100) //4


sezeof(p)分别是多少字节?




在网上搜了很多笔试题,以下这个版本的最多,但只有几道题有答案,有答案的我都原封不动抄过来(应该是对的),其它的我都写上了自己的答案及理解,请大家指正!
   
1. 以下三条输出语句分别输出什么?[C易](已验证)
char str1[]       = "abc";
char str2[]       = "abc";
const char str3[] = "abc"; 
const char str4[] = "abc"; 
const char* str5  = "abc";
const char* str6  = "abc";
cout << boolalpha << ( str1==str2 ) << endl; // 输出什么?
cout << boolalpha << ( str3==str4 ) << endl; // 输出什么?
cout << boolalpha << ( str5==str6 ) << endl; // 输出什么?


答:分别输出false,false,true。
str1和str2都是字符数组,每个都有其自己的存储区,它们的值则是各存储区首地址,不等;
str3和str4同上,只是按const语义,它们所指向的数据区不能修改。
str5和str6并非数组而是字符指针,并不分配存储区,其后的“abc”以常量形式存于静态数据区,
而它们自己仅是指向该区首地址的指针,相等。由此可见,相同的静态数据只有一份拷贝!!(刚开始我还以为都是false呢)


准确:
第一道题应该是和编译器优化相关的,不同的编译器和编译器设置结果不同.
在Borland的编译器中如果不设置Merge duplicate strings选项的结果就是false,false,false




12. 以下代码中的两个sizeof用法有问题吗?[C易](已验证)
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' );
}
char str[] = "aBcDe";
cout << "str字符长度为: " << sizeof(str)/sizeof(str[0]) << endl;
UpperCase( str );
cout << str << endl;


答:函数内的sizeof有问题。根据语法,sizeof如用于数组,只能测出静态数组的大小,无法检测动态分配的或外部数组大小。
函数外的str是一个静态定义的数组,因此其大小为6,函数内的str实际只是一个指向字符串的指针,
没有任何额外的与数组相关的信息,因此sizeof作用于上只将其当指针看,一个指针为4个字节,因此返回4。




13. 非C++内建类型 A 和 B,在哪几种情况下B能隐式转化为A?[C++中等](大概知道,不熟)
答:
a. class B : public A { ……} // B公有继承自A,可以是间接继承的
b. class B { operator A( ); } // B实现了隐式转化为A的转化
c. class A { A( const B& ); } // A实现了non-explicit的参数为B(可以有其他带默认值的参数)构造函数
d. A& operator= ( const A& ); // 赋值操作,虽不是正宗的隐式类型转换,但也可以勉强算一个




4. 以下代码有什么问题?[C++易](已验证,但实际上出错的语句是b.fun();)
struct Test
{
    Test( int ) {}
    Test() {}
    void fun() {}
};
void main( void )
{
    Test a(1);
    a.fun();
    Test b(); //实际上相当于声明了一个函数,函数名为b,返回值为Test类型
    b.fun();  //显然函数名后面是不能带.fun()的,编译出错
}


答:变量b定义出错。按默认构造函数定义对象,不需要加括号。




5. 以下代码有什么问题?[C++易](已验证)
cout << (true?1:"1") << endl;
答:三元表达式“?:”问号后面的两个操作数必须为同一类型。




8. 以下代码能够编译通过吗,为什么?[C++易](已验证)
unsigned int const size1 = 2;
char str1[ size1 ];
unsigned int temp = 0;
cin >> temp;
unsigned int const size2 = temp;
char str2[ size2 ];
答:str2定义出错,size2非编译器期间常量,而数组定义要求长度必须为编译期常量。




2. 以下反向遍历array数组的方法有什么错误?[STL易](已验证)
vector array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 3 );
for( vector::size_type i=array.size()-1; i>=0; --i ) // 反向遍历array数组
{
    cout << array[i] << endl;
}


答:首先数组定义有误,应加上类型参数:vector<int> array。
其次vector::size_type被定义为unsigned int,即无符号数,这样做为循环变量的i为0时再减1就会变成最大的整数,导致循环失去控制。




9. 以下代码中的输出语句输出0吗,为什么?[C++易](已验证)
struct CLS
{
    int m_i;
    CLS( int i ) : m_i(i) {}
    CLS()
    {
        CLS(0);
    }
};
CLS obj;
cout << obj.m_i << endl;


答:不能。之所以不行,其实原因很简单,你在cls()
{
 cls(0)
}
中,cls(0)这是一个局部对象,用完就没有了(:




10. C++中的空类,默认产生哪些类成员函数?[C++易](已验证,有意思,以前都没听过,但实际上有可能这些函数并不被合成)
答:
class Empty
{
public:
    Empty();                          // 缺省构造函数
    Empty( const Empty& );            // 拷贝构造函数
    ~Empty();                         // 析构函数
    Empty& operator=( const Empty& ); // 赋值运算符
    Empty* operator&();               // 取址运算符
    const Empty* operator&() const;   // 取址运算符 const
};




 
3. 以下两条输出语句分别输出什么?[C++难](已验证)
float a = 1.0f;
cout << (int)a << endl;
cout << (int&)a << endl;
cout << boolalpha << ( (int)a == (int&)a ) << endl; // 输出什么?
float b = 0.0f;
cout << (int)b << endl;
cout << (int&)b << endl;
cout << boolalpha << ( (int)b == (int&)b ) << endl; // 输出什么?


答:分别输出false和true。注意转换的应用。(int)a实际上是以浮点数a为参数构造了一个整型数,该整数的值是1,
(int&)a则是告诉编译器将a当作整数看(并没有做任何实质上的转换)。因为1以整数形式存放和以浮点形式存放其内存数据是不一样的,
因此两者不等。对b的两种转换意义同上,但是0的整数形式和浮点形式其内存数据是一样的,因此在这种特殊情形下,
两者相等(仅仅在数值意义上)。
注意,程序的输出会显示(int&)a=1065353216,这个值是怎么来的呢?前面已经说了,1以浮点数形式存放在内存中,按ieee754规定,其内容为0x0000803F(已考虑字节反序)。这也就是a这个变量所占据的内存单元的值。当(int&)a出现时,它相当于告诉它的上下文:“把这块地址当做整数看待!不要管它原来是什么。”这样,内容0x0000803F按整数解释,其值正好就是1065353216(十进制数)。
通过查看汇编代码可以证实“(int)a相当于重新构造了一个值等于a的整型数”之说,而(int&)的作用则仅仅是表达了一个类型信息,意义在于为cout<<及==选择正确的重载版本。


6. 以下代码有什么问题?[STL易](已验证)
typedef vector IntArray;
IntArray array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 2 );
array.push_back( 3 );
// 删除array数组中所有的2
for( IntArray::iterator itor=array.begin(); itor!=array.end(); ++itor )
{
    if( 2 == *itor ) array.erase( itor );
}


答:同样有缺少类型参数的问题。另外,每次调用“array.erase( itor );”,被删除元素之后的内容会自动往前移,导致迭代漏项,应在删除一项后使itor--,使之从已经前移的下一个元素起继续遍历。
 
11. 写一个函数,完成内存之间的拷贝。[考虑问题是否全面]
答:
void* mymemcpy( void *dest, const void *src, size_t count )
{
    char* pdest = static_cast<char*>( dest );
    const char* psrc = static_cast<const char*>( src );
    if( pdest>psrc && pdest<psrc+cout ) 能考虑到这种情况就行了
    {
        for( size_t i=count-1; i!=-1; --i )
                pdest[i] = psrc[i];
    }
    else
    {
        for( size_t i=0; i<count; ++i )
            pdest[i] = psrc[i];
    }
    return dest;
}
相当于把库函数memcpy和memmove合在了一起


14.(已验证)
执行 
  c=5;
  a=2+(c+=c++,c+8,c++);
a应该得多少呢?
答:
在VC6.0,7.0中是a是13(过程: c+=c, c++, a=c+2, c++)
这个问题去年曾经有过很长时间的讨论,标准答案如下:


C语言(以及C++语言)标准没有规定在一个表达式中对同一个内存地址(变量)做超过一次的自加(或自减)操作的具体实现结果。并且特别说明,应该避免这样的代码。


我曾经用四种不同的编译器得到了四种不同的结果。


标准中说:这种表达式的运算结果是“不可预期”的。


好像只有中国的学校会在考试中出这种题目,下次你可以去下载一个ISO的C语言标准去跟老师理论,没准他会觉得你才华出众,给你一个满分。


我们公司的编程规范中就有一条:“不准在同一个表达式中对同一个变量作两次或更多的自加操作,每个变量最多只能使用一次这种操作。不允许使用带有自加(或自减)操作的表达式做函数的参数”。前一条规定说的就是这个问题,至于后一条规定,因为某些函数可能会在将来替换成宏,而宏之中可能会将这个表达式引用多次,这样就造成了错误。


如果编写的代码出现这样的问题,在我们公司是要扣分的。


  
15.请教类型:jmp_buf有参宏:setjmp 库函数:longjmp都怎么用?不太明白(待验证,实在很少用)


jmp_buf jmp;


.........
if(setjmp(jmp) == 1) ......... //处理异常


............


if(..........) longjmp(jmp, 1);  //发生异常,跳转




setjmp/longjmp跟goto根本就是两个东西,goto的意义,是往哪里去,setjmp/longjmp则是回到哪里去,并且setjmp会保留现场,由longjmp返回时会恢复现场。




16.:  关于八进制转为十进制的程序问题??(待写)
/*下面的  n=n*8+*p-'0'; 我看不来呀??哪位给我讲下!
int main()
{
int n=0, tmp=1;
char *p; char a[6];
p=a;
gets(p);
while(*(p)!='\0')
{

n=n*8+*p-'0';     /*就是这里*/
p++;
}
printf("%d", n);
system("pause");
return 0;
}




19.
请教个位大哥,在C语言中怎样编写代码实现把浮点数转换成字符串,急急!!!!(待写)


函数名: gcvt 
功  能: 把浮点数转换成字符串 
用  法: char *gcvt(double value, int ndigit, char *buf); 
程序例: 
 
#include <stdlib.h> 
#include <stdio.h> 
 


int main(void) 

   char str[25]; 
   double num; 
   int sig = 5; /* 需要转化的位数*/ 
 


   /* 一般浮点数*/ 
   num = 9.876; 
   gcvt(num, sig, str); 
   printf("string = %s\n", str); 
 


   /* 负数*/ 
   num = -123.4567; 
   gcvt(num, sig, str); 
   printf("string = %s\n", str); 
 


   /* 带指数*/ 
   num = 0.678e5; 
   gcvt(num, sig, str); 
   printf("string = %s\n", str); 
   return(0); 





char *ecvt(double value,int ndigit,int *decpt,int *sign) 将浮点数value转换成字符串并返回该字符串 


char *fcvt(double value,int ndigit,int *decpt,int *sign) 将浮点数value转换成字符串并返回该字符串 


char *gcvt(double value,int ndigit,char *buf) 将数value转换成字符串并存于buf中,并返回buf的指针 






可以使用这些函数 ...


貌似在 stdlib.h 这个库中的 ..




20.题目:(待写)
对序列(16,12,24,16,4,8,20,2,30,18)排序后,折半查找值为12,45的元素,若查找成功,输出元素所在位置,否则输出0。




21.
#include "stdafx.h"
#pragma pack(8)


struct s1{
short a;
long b;
};


struct s2{
char c;
s1 d;
__int64 e;
};
#pragma pack()


void main(){
int i=sizeof(s2);
}


22.编写一个函数判断一个正整数是否是对称数,对称数例如(3,22,121,1221,12321等)要求不能使用将整数转换为字符的库函数!(待写)




23.找出下面的程序中有什么错误,一一列出(微软)(已验证)
#define mkupper(c)  ((c)-'a'+'A')


void StringToUpper (char * pStr)
{
while(pStr)
{
*pStr=mkupper(*pStr);
pStr++;
}
}


int main()
{
char *tmp="aBcdef";
StringToUpper(tmp);
return 0;
}
答:
错误1:while(pStr)=>while(*pStr)
错误2:不能将常量字符串的地址传递给StringToUpper,并通过*pStr修改它,程序会挂的






#include <stdio.h>
#include <malloc.h>
void main()
{
   char * p=(char*)malloc(0);
   printf("%X\n",p);
   printf("%d",_msize(p));//输出0
}


C99标准(ISO/IEC 9899:1999 (E))上说:


If the size of the space requested is zero, the behavior is implementationdefined:
either a null pointer is returned, or the behavior is as if the size were some
nonzero value, except that the returned pointer shall not be used to access an object.


如果所请求的空间大小为0,其行为由库的实现者定义:可以返回空指针,也可以让效果跟申请某个非0大小的空间一样,所不同的是返回的指针不可以被用来访问一个对象。




"分配的内存至少要包括管理结构的长度,所以一次malloc()操作,即便是malloc(0),也会实际分配至少16字节的内存"
malloc()调用返回给用户的是mem指针(chunk + 8),chunk 是管理结构头指针,也就是16字节中的后8字节会被用户数据覆盖。




下面是malloc实现中的注释


 For large (>= 512 bytes) requests, it is a pure best-fit allocator,
    with ties normally decided via FIFO (i.e. least recently used).
  * For small (<= 64 bytes by default) requests, it is a caching
    allocator, that maintains pools of quickly recycled chunks.
  * In between, and for combinations of large and small requests, it does
    the best it can trying to meet both goals at once.
  * For very large requests (>= 128KB by default), it relies on system
    memory mapping facilities, if supported.



面试题:
1. 语言: C 与 C++ 的优缺点, 尤其在大矩阵运算, 三维图像处理, 及与其它软件和数据库的交接等方面. 如果一个程序既需要大量运算又要一个好的用户界面并与其它软件大量交流, 应该怎样选合适的语言.




2. 算法: 大矩阵运算时, 算法上和遍程上该有哪些考虑. 能分别举几个适合于解线性和非线性方程组算法吗?




3. 图形学: 在编写大规模三维图像处理程序时 (类似于AutoCAD), 应注意哪些因素, 使得图像运行平稳, 显示明确, 屏幕不冻结? 显示复杂三维图象时, 怎样才能更好地突出你所感兴趣的部件?




4. 数据结构: 数据量中等, 分类有限, 检索很少. 在此情况下, 用C/C++能高速处理吗? 可以多用户分享吗? 该注意哪些因素? 假如每个项目都有三维图象数据, 材料数据,工艺数据和运算结果, 在不使用数据库的情况下, 该采用哪种数据结构?


5. INTERNET技术: 如有一个专用设计软件放在专用服务器上, 而用户通过INTERNET使用这一软件. 他们的设计项目的运算可分为前期图像处理, 中期数据运算, 和后期结果处理和显示. 该怎样合理而又安全地在服务器和用户终端间分配程序和数据?


6. 安全保密: 请就以下三个方面谈谈看法: A. 如按照以上第5点所说方式使用软件, 如何让用户放心, 他们的设计/知识产权不会给别人窃取. B. 如何防盗版, 包括合法用户买一份而多重使用. C. 如果几个人同时工作于同一项目上, 怎样使得某个人的工作及时安全地反映到其他人的工作/工作环境中, 但又不干扰他们的工作.


7. 请你简单叙述一下将一个实心立体网格化并使所有网格小于给定标准的程序结构.


8. 在用循环法数值解大型线性方程组是, 用什么方法加速解的收敛? 怎样判断是否收敛?




#include "stdafx.h"
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <fstream>
#include <functional>


using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
istream_iterator <int> input( cin );
istream_iterator <int> endofstream;
vector <int> vec;
copy(input,endofstream,back_inserter(vec));
sort(vec.begin(),vec.end());
ostream_iterator <int> output( cout," ");
unique_copy(vec.begin(),vec.end(),output);
return 0;
}
stl 我按照c++ primer写了一个程序,是输入一系列整数数,排序再输出,为什么在vc里面运行 根本不能
输入为什么?
答:
用了ctrl + A结束后,正常了....




//题目为:不用strcat,下面是方法。为什么第一次不行,而第二次OK?
#include<stdio.h>
#include<string.h>
int main()
{
int i;
char c1[10],c2[5];
gets(c1);
gets(c2);
for(i=0;i<=strlen(c2);i++)
c1[strlen(c1)+i]=c2[i];
puts(c1);
return 0;
}










#include<stdio.h>
#include<string.h>
int main()
{
int i;
char c1[10],c2[5];
gets(c1);
gets(c2);
int k=strlen(c1);




for(i=0;i<=strlen(c2);i++)
c1[k+i]=c2[i];
puts(c1);
return 0;
}






从1-30个数中选出8个数,让它们的和为N(可指定),求这样的数有几组,并打印出来。




有A箱子长宽高分别为a*b*c共x只, B箱子长宽高分别为i*j*k共y只, 要把这些箱子放到一个大箱子里去,求大箱子的体积。(要求大箱子体积最小)




看到许多初学者的发问帖子,感触良多,故作此文章,初学者聊且一看,经验丰富者帮助点评。对于那些学习C语言的目的就是想考什么证书的人,谢谢您请关掉此窗口。


我已经用了12年C语言了,应该还算是经验丰富把,有些建议要说给初学者们。


编程语言其实是一个很初级的工具,但是你又必须熟练的掌握它,学懂一门编程语言就好像学会了写字,但是会写字的人不见得会写文章,而会写文章又不见的写得好。可是如果你不会写字,那就一定写不出文章来。


首先,在学习C语言之前,应该学好计算机基础。里面的很多概念对于C程序员都是非常重要的。如果你在着手学习C之前,或者已经开始学习C,但是碰到了很多问题,应该再把计算机基础的书拿来好好看看。


如果你有足够的耐心,十足的毅力,应该再学习C语言之前学学汇编,这会让你对许多比较细腻的概念有清醒的认识,如果你不是那么有耐心(恕我直言,大部分人可能没有)。那么可以在看完一遍C语言的教材后再看,但是一定要看一遍,相信我一定会受益匪浅。


看到有些人发问的帖子,很明显的没有仔细的思考过问题,或者没有认真地查阅过书籍,因为其中的语法和逻辑错误实在是不能理解。想来如果你的语文作业上面满篇都是错字,老师一定不会放过你。为什么不先打好基础呢?有些人抱怨说因为教材不好,老师水平不行等等。但是我本人就是在TC2下学习C语言的,那时候除了谭浩强的书,也几乎找不到什么别的书。我不打算就谭浩强的书发表什么意见,那也是在称不上是一本好书,但是如果这本是能学好,全部看好,都记住,也应该有相当的水平了。建议不管看什么书,先认真地看懂,不要贪速度,应该力求深入的理解。


如果你能够比较熟练的解决一本教材上的所有习题,那么就应该转入对算法的学习,尽管此时你的C语言还称不上精通,有许多细节问题还不了解,许多问题还没有碰到,但是这些问题会在后面的工作和学习中得到解决的。


过去,有个著名的公式,大概是:程序=语言+算法+数据,不知道现在还提不提这个了。可能现在要加上更多的内容:项目管理、质量控制、代码规范…………。但是这个公式还是有相当的参考价值,还是用写文章来类比,语言好比文字,算法是文章的思想,数据是文章的内容。所以在经过一个阶段的识字之后,应该试着发表一下自己的思想了。


经过一段零零散散的算法学习,对“算法”这两个字有了概念之后,应该系统地对算法进行学习,这个过程是与数据结合在一起的,应该看看数据结构,而且必须熟练的掌握。在这里提到的一本书是《运筹学》,里面的算法大都可以用计算机实现,我推荐这本书的原因在于,它不仅介绍了特定问题的算法,而且详细解释了为什么要这样算,怎么得出这个算法的,等等。对于提高思考问题的能力有很大帮助。


如果你的精力和时间允许,现在就应该开始大量的阅读和编写代码了,两者同样重要。“读书破万卷,下笔如有神”,尽管这种学习方法效率较低,而且很枯燥,但是应该看到,古代的这种教育方式培养了千古文豪,而现在的语文教育培养出来的…………(唉,中小学语文教育的现状大家都知道,我就是受害者)。读代码确实是一件非常辛苦的事情,我曾经试图阅读全部的Linux内核原代码,最后只看了不到十分之一,而其中看懂领会的,也就一半而已,但还是感到有很大帮助。至于大量编写代码,理由很简单:实践性的技术要在实践中提高。但是要注意,如果你已经学完了C语言和数据结构(而且学得不错),那就不应该专注于那些小程序了,那根本就是在浪费时间,此时应该编写有些规模的,具有一定实用性的程序。并在这个过程中开始领会软件工程的一些思想。第一个写出来的程序一定是错误百出,一点点地修改,一点点地调试,一定会通过的。对于写代码,说一个我本人的经历,我第一遍看谭浩强的那本书,看到条件分支的时候,突然很兴奋,想要写点什么,于是看了一些 TC2的帮助,懂得了图形编程,就自己写了一个水果赌盘的游戏,可能有人在游戏厅见过,就是可以压什么苹果橙子之类的。各位可以想象一下,当时我还不会数组,不知道循环,于是所有的这类东西都是用goto来完成的,这个历史上最蹩脚的程序居然也正常运行了,后来我发现原来可以使用循环,于是将这段代码替换掉,学到数组的时候,终于将那些小灯在屏幕上的位置放到了数组里,学到文件的时候,将图形放进了二进制文件(原本都是一条线、一个点画出来的),记不得经过了多少次修改,总之程序能运行之后,长度从2700行变成了127行。所以,想学好编程是要有点毅力的。


最后发表一下先学习C还是先学习C++的问题,这个问题见仁见智,我的意见是,先学习C。


尽管现在我很少用C了,但是C语言确实更加基础,一个C++的高手要考虑的一些问题(比如内存的操作方面的问题),C语言的初学者可能就必须有所了解,否则会犯错误。这些只是迟早是要掌握的,但是因为C++关注更高层的概念,所以在学习C++的过程中这些问题可能被忽略了,以至于有人用了一两年C++,还是有些问题不是很清楚。另一个主要的原因是:C++太优秀了,而C++的程序员会在某种程度上感觉自己比C程序员高明(他们确实有理由这样),于是学完C+ +之后你可能就不屑于学习C所关注的内容,这样的话会错过提高的很好机会。


最后希望各位的学习过程顺利,进步迅速!!




1。假设有一个4节点的单链表,请设计一个C语言递归函数,实现链表的逆序。


2。编写一个C函数,实现将无符号字符类型数的高位和低位的逆转。


我有三个文件,内容分别如下:


// @(#) TestTemplate.h


template < class T >
class TestTemplate
{
public:
TestTemplate(void);
};




// @(#) TestTemplate.cpp
#include "testtemplate.h"


template < class T >
TestTemplate< T >::TestTemplate(void)
{
}




// @(#) Main.cpp
#include "TestTemplate.h"


void main() {
TestTemplate< int > a;
}




链接的时候出现如下错误:
VCTest error LNK2019: 无法解析的外部符号 "public: __thiscall TestTemplate<int>::TestTemplate<int>(void)" (??0?$TestTemplate@H@@QAE@XZ) ,该符号在函数 _main 中被引用




请问是怎么回事,应该如何解决!
da:
现在的编译器不支持模版分离编译。。 



// @(#) TestTemplate.cpp
#include "testtemplate.h"


template < class T >
TestTemplate< T >::TestTemplate(void)
{
}
放到
"testtemplate.h"中
模板声明和实现必须要在一起


eg:
int a() { return true;}
《C++ Primer》中指出true其实就是1,但公司内部的编程规范同时提示:不允许在int类型的函数中返回C++内置类型true/false(自定义的TRUE/FALSE是允许的),说会有移植性问题,请问各位大侠,这个条款是否正确?
da:
这个条款是正确。bool和BOOL是不同的。bool是单字节的,sizeof(bool)=1,而BOOL其实就是int型,sizeof (BOOL) = sizeof(int) = 4 (VC下)。true = 00000001B,TRUE = 0x0001。




如何写开方程序?
如:
15451454


我看到上面有0MS就出结果的,我用了524MS。真不知道是怎么做的。
希望各位高手给个算法思想,给代码就更好,谢谢谢谢!!!!
青蛙的约会


Time Limit:1000MS Memory Limit:10000K
Total Submit:4356 Accepted:455


Description
两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面。它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止。可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置。不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的。但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的。为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面。
我们把这两只青蛙分别叫做青蛙A和青蛙B,并且规定纬度线上东经0度处为原点,由东往西为正方向,单位长度 1米,这样我们就得到了一条首尾相接的数轴。设青蛙A的出发点坐标是x,青蛙B的出发点坐标是y。青蛙A一次能跳m米,青蛙B一次能跳n米,两只青蛙跳一次所花费的时间相同。纬度线总长L米。现在要你求出它们跳了几次以后才会碰面。




10.(确定)
转帖:
VC中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;


否则必须为n的倍数。下面举例说明其用法。


#pragma pack(push) //保存对齐状态


#pragma pack(4)//设定为4字节对齐


struct test


{


char m1;


double m4;


int m3;


};


#pragma pack(pop)//恢复对齐状态


以上结构的大小为16,下面分析其存储情况,首先为m1分配空间,其偏移量为0,满足我们自己设定的对齐方式(4字节对齐),m1占用1个字节。接着开始为 m4分配空间,这时其偏移量为1,需要补足3个字节,这样使偏移量满足为n=4的倍数(因为sizeof(double)大于n),m4占用8个字节。接着为m3分配空间,这时其偏移量为12,满足为4的倍数,m3占用4个字节。这时已经为所有成员变量分配了空间,共分配了16个字节,满足为n的倍数。如果把上面的#pragma pack(4)改为#pragma pack(16),那么我们可以得到结构的大小为24。
=========
编译器不同在存放结构体方式可能不同,因此对齐也会有不同




参看
blog.csdn.net/freefalcon
中sizeof里面有关结构体部分




说了这么一大堆,
个人觉得这不过是编译器的一种偷


希望大家能给我比较深入地解释。以下几个问题可能有点重复,希望大侠见谅!
1. 为什么在1和2中不按4字节对齐(也就是size = 4)而3中却按4字节对齐了?
2. 为什么4和5的不按4字节对齐(也就是size = 8),且为什么size都一样,为6?
3. 为什么6中按字节对齐,而4和5却不是?
1.
struct Node //size = 1
{
char ch;
};


2.
struct Node //size = 2
{
char ch;
char ch1;
};


3.
struct Node //size = 4
{
char ch;
short sh;
};


4.
struct Node //size = 6
{
char ch1;
char ch[2];
short sh;
};


5.
struct Node //size = 6
{
char ch1;
char ch[3];
short sh;
};


6.
struct Node //size = 8
{
char ch1;
char ch[4];
short sh;
};
这是我的例子:
#include <stdio.h>
#include <stdlib.h>
#pragma pack(4)//设定为4字节对齐。没有这句时,返回16。有时返回12。如果设置为1,返回11
struct A{
char i;
short b;
double c;
};


int main( int i , char * pp){


printf( "%d",sizeof(A));




return 0;
}




问题:共有N种面值的邮票,存在整数R,使得用不超过M枚的上述面值的邮票可以贴出从1开始一直到R的有面值,但不能R+1。例如:面值(1, 4,7,8的邮票不超过3张可以贴出1~24间的所有邮资,但贴不出25。)请从键盘输入M和N,寻找一种确定每种邮票面值的方案,使得该方案在M和N的限制下对应的R值最大。


楼上。。。我特意去找了99年全国信息学分区联赛高中组的试题,怎么没看到啊。。


第四届全国青少年信息学(计算机)奥林匹克分区联赛复赛试题
(高中组 竞赛用时:3小时)


1.火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上、下车,但上、下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为a人。从第3站起(包括第3站)上、下车的人数有一定规律:上车的人数都是前两站上车人数之和,而下车人数等于上一站上车人数,一直到终点站的前一站(第n-1站),都满足此规律。现给出的条件是:共有N个车站,始发站上车的人数为a,最后一站下车的人数是m(全部下车)。试问x站开出时车上的人数是多少?
输入:a,n,m和x
输出:从x站开出时车上的人数。 {20%}




是不是这套卷子?




10.(已验证)
int func(int a)
{
int b; // 沒有初始化
switch(a)
{
case 1: 30;
case 2: 20;
case 3: 16;
default: 0
}
return b; // 未知數
}


b是一个局部变量,理论上来说,他应为一个不确定的数
(局部变量未初始化的值是不确定的;全局变量和静态变量未初始化,默认值为0),


printf( "%d",func(1));//如-858993640













  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一些可能会在C语言面试中出现的问: 1. 什么是指针? 指针是一个变量,其值为另一个变量的地址。在C语言中,指针变量用于存储地址,以便可以访问该地址处存储的数据。 2. 如何声明一个指针变量? 指针变量的声明方式如下: ``` int *p; ``` 其中,`int`是指向的数据类型,`*`表示该变量是一个指针变量,`p`是变量名。 3. 如何使用指针访问变量的值? 使用指针访问变量的值需要使用解引用运算符`*`,例如: ``` int a = 10; int *p = &a; printf("%d", *p); // 输出:10 ``` 4. 什么是动态内存分配? 动态内存分配是指在程序运行时根据需要分配内存空间。在C语言中,可以使用`malloc()`函数分配动态内存空间,使用`free()`函数释放已分配的内存空间。 5. 如何使用结构体? 结构体是一种用户自定义的数据类型,可以使用关键字`struct`定义。例如: ``` struct person { char name[20]; int age; }; ``` 可以使用以下方式定义结构体变量: ``` struct person p1; p1.age = 20; strcpy(p1.name, "Tom"); ``` 6. 什么是指针数组? 指针数组是一个数组,其中每个元素都是指针类型。例如: ``` int a = 10, b = 20, c = 30; int *arr[] = {&a, &b, &c}; printf("%d", *arr[0]); // 输出:10 ``` 7. 什么是函数指针? 函数指针是一个指向函数的指针变量。例如: ``` int add(int a, int b) { return a + b; } int (*p)(int, int) = add; printf("%d", (*p)(1, 2)); // 输出:3 ``` 其中,`p`是一个指向函数`add`的指针变量,可以通过`(*p)(1, 2)`调用该函数。 以上是一些常见的C语言面试,希望能对你有帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值