strcpy,strncpy,char*s ,char s[]


[原]程序员笔试题---说说char *s 和char s[]


一、

关于char *s 和char s[]区别的笔试题,虽说占的分数不多,但是基本每家公司都会考!所以在此做个小总结!避免自己在犯错误!当初就是因为这么小的问题,被一家大公司拒之门外!基础很重要的啊亲!

看下面的代码:

char *s="123456";
	cout<<*s<<endl;//1
	cout<<s<<endl;//123456
	
	printf("%x\n",*s);//31
	printf("%x\n",*(s+1));//32
	printf("%x\n",s);//432024
	printf("%s\n",s);//123456
你看明白了吗?

知道原因不?

知道原因的敬请留言

二、

char a[]="hello";

char *s="hello";

数组a分配在栈上,内容可以修改;

s内容在常量区,内容不允许修改!

还有一道题是:我在另外一篇文章已经说到!点击看下!

总感觉一篇文章只写上面那么多,有点像是忽悠人,故加点内容哈!

昨天有人问了这样一题目:

#include "stdafx.h"
#include <iostream>

using namespace std;

class B {
public:
	virtual void fun(int i = 1) { cout <<"B::"<<i << endl; }
	
};

class D : public B {
public:
	virtual void fun(int i = 3) { cout <<"D::"<< i << endl; }
	
};

int main(int argc, char* argv[])
{
	B* p1;
	B* p2 = new B;
	B* p3 = new D;
	
	p2->fun();
	p3->fun();
	return 0;
}

输出什么:

一开始很多人的回答是: 1 和3  理由:对象指针指向自己的虚方法。

答案真的是这样吗?

正确答案是:1 和1

这是为什么。决不要重新定义继承而来的缺省参数值。Effective C++ 第38款说的很清楚。虚函数是动态绑定。

为什么C++坚持这种有违常规的做法呢?答案和运行效率有关。如果缺省参数值被动态绑定,编译器就必须想办法为虚函数在运行时确定合适的缺省值,这将比现在采用的在编译阶段确定缺省值的机制更慢更复杂。做出这种选择是想求得速度上的提高和实现上的简便,所以大家现在才能感受得到程序运行的高效;当然,如果忽视了本条款的建议,就会带来混乱。


查看评论
  • 6楼qitian00082012-09-30 16:43

    [reply]wojiushiwo987[/reply] 嗯是的!

  • 5楼qitian00082012-09-30 16:39

    [reply]shunqiziranhao007[/reply] 分析的很不错哦!

  • 4楼shunqiziranhao0072012-09-30 15:25

    [code=cpp] 第2个问题我也遇到了,后来找到了下面的资料。 《C程序设计语言V2en》 5.5 Character Pointers and Functions There is an important difference between these definitions: char amessage[] = "now is the time"; // an array char *pmessage = "now is the time"; // a pointer amessage is an array, just big enough to hold the sequence of characters and '\0' that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents. [/code] ———— 第3个问题,在《EffectiveC++V3cn》p180,条款37:绝不重新定义继承而来的缺省参数值,详细论述了。看到博主给的是条款38,所以在这里补充 版本和页码。不知道博主看的是第几版的。

  • 3楼shunqiziranhao0072012-09-30 15:17

    下面我是关于1的分析,不知道对不对? [code=cpp] #include <iostream> using namespace std; int main() { char *s = "123456"; // s是指向char的指针,*s就是取s所指地址开始的1字节内存的数据也就是 1的 // ASCII值49,由于*s的类型是char,所以输出 1 。 // 这句相当于 printf("%c", *s); cout << *s << endl; // 由于s是指向字符类型的指针,所以1字节1字节读取s所指地址开始的内存中的数 // 据,直到遇到字符串结束符0为止。所以输出为 123456 . cout << s << endl; // 要求输出 整型值的十六进制格式。*s就是取s所指地址开始的1字节内的数据也 // 就是 1的ASCII值49 ,但是它的类型是char,所以会隐式转型为 int ,结果就 // 是 31(49的十六进制格式) 了。 printf("%x\n", *s); // 要求输出 整型值的十六进制格式。s+1 表示 s所指向地址加上1*1(由于s是指 // 向char的,所以位移单位为1,如果指向的是int,那么位移单位就是4了,就变 // 成了 1*4 。) *(s+1) 取s+1所指地址开始的1字节内存中的数据,也就是2的 // ASCII值50,然后隐式转型为 int ,结果为 32 (50的十六进制格式)。 printf("%x\n", *(s+1)); // 这里是打印s这个指针变量的值,其值是随机的,因为系统用来存储 "123456" 的 // 内存地址是变化的。 printf("%x\n", s); // 打印字符串,从s所指地址开始,1字节1字节的读取内容,直到遇到字符串结束 // 符0为止。 printf("%s\n", s); return 0; } /* 输出效果: 1 123456 31 32 1307838 123456 */ [/code]

  • 2楼wojiushiwo9872012-09-30 14:14

    Effective C++ 第37款,细读了下是这个理。一边是动态绑定、一边是静态类型,所以才有了此规定——“绝不重新定义继承而来的缺省参数值”。





第一种情况:
char* p="how are you ?";
char name[20]="ABCDEFGHIJKLMNOPQRS";

 

strcpy(name,p);   //name改变为"how are you ? OPQRS "     ====>错误!
strncpy(name,p,sizeof(name))    //name改变为"how are you ?      "       ====>正确!

第二种情况:
char* p="how are you ?";
char name[20];

strcpy(name,p);    //name改变为"how are you ? 未知字符 "     ====>错误!
name[sizeof(name)-1]='/0'      //和上一步组合,得到正确的结果!
strncpy(name,p,sizeof(name));        //name改变为"how are you ?      "      ====>正确!

第三种情况:
char* p="how are you ?";
char name[10];

strcpy(name,p);      //name改变为"how are yo"     ====>无结束符'/0',错误!
name[sizeof(name)-1]='/0'      //和上一步组合,弥补结果。但要注意,字符传递错误!
strncpy(name,p,sizeof(name));      //和单纯的一步strcpy结果一样!

 

总结:strcpy
如果源长>目标长,则将源长中等于目标长的字符拷贝到目标字符串
如果源长<目标长,则源长全部拷贝到目标字符串,不包括'/0'
strncpy
如果目标长>指定长>源长,则将源长全部拷贝到目标长,自动加上'/0'
如果指定长<源长,则将源长中按指定长度拷贝到目标字符串,不包括'/0'
如果指定长>目标长,error happen!

 

 

 

/***************************************************************************************************

东去东来总结:

strcpy(),以源串中的'/0'为拷贝结束标志,直到遇到该NULL为止,然后将NULL拷贝上.

strncpy()以第三个参数N为拷贝结束标志,如果source的长度小于N,则剩余的字符全部用NULL填充.

              如果source的长度大于N,则从source中截取前N个字符,拷贝过去.



C语言中函数strcpy ,strncpy ,strlcpy的用法

strcpy ,strncpy ,strlcpy的用法

好多人已经知道利用strncpy替代strcpy来防止缓冲区越界。

但是如果还要考虑运行效率的话,也许strlcpy是一个更好的方式。

1. strcpy

strcpy 是依据 /0 作为结束判断的,如果 to 的空间不够,则会引起 buffer overflow。strcpy 常规的实现代码如下(来自OpenBSD 3.9):

char * strcpy(char *to, const char *from)

{

       char *save = to;

 

       for (; (*to = *from) != '/0'; ++from, ++to);

       return(save);

}

但通常,我们的 from 都来源于用户的输入,很可能是非常大的一个字符串,因此 strcpy 不够安全。

2. strncpy

在 ANSI C 中,strcpy 的安全版本是 strncpy

char *strncpy(char *s1, const char *s2, size_t n);

但 strncpy 其行为是很诡异的(不符合我们的通常习惯)。标准规定 n 并不是 sizeof(s1),而是要复制的 char 的个数。一个最常见的问题,就是 strncpy 并不帮你保证 /0

结束。

char buf[8];

strncpy( buf, "abcdefgh", 8 );

看这个程序,buf 将会被 "abcdefgh" 填满,但却没有 /0 结束符了。

另外,如果 s2 的内容比较少,而 n 又比较大的话,strncpy 将会把之间的空间都用 /0 填充。这又出现了一个效率上的问题,如下:

char buf[80];

strncpy( buf, "abcdefgh", 79 );

上面的 strncpy 会填写 79 个 char,而不仅仅是 "abcdefgh" 本身。

strncpy 的标准用法为:(手工写上 /0)

strncpy(path, src, sizeof(path) - 1);

path[sizeof(path) - 1] = '/0';

len = strlen(path);

3. strlcpy

// Copy src to string dst of size siz. At most siz-1 characters

// will be copied. Always NUL terminates (unless siz == 0).

// Returns strlen(src); if retval >= siz, truncation occurred.

size_t   strlcpy(char *dst, const char *src, size_t siz);

而使用 strlcpy,就不需要我们去手动负责 /0 了,仅需要把 sizeof(dst) 告之 strlcpy 即可:

strlcpy(path, src, sizeof(path));

len = strlen(path);

if ( len >= sizeof(path) )

       printf("src is truncated.");

并且 strlcpy 传回的是 strlen(str),因此我们也很方便的可以判断数据是否被截断。

[* 一点点历史 *]

strlcpy 并不属于 ANSI C,至今也还不是标准。

strlcpy 来源于 OpenBSD 2.4,之后很多 unix-like 系统的 libc 中都加入了 strlcpy 函数,我个人在 FreeBSD、Linux 里面都找到了 strlcpy。(Linux使用的是 glibc,

glibc里面有 strlcpy,则所有的 Linux 版本也都应该有 strlcpy)

但 Windows 下是没有 strlcpy 的,对应的是strncpy和memset函数

1>strncpy    

原型:extern  char *strncpy(char   *dest,   char   *src,   int   n);                    

用法:#include   <string.h>  

功能:把src所指由NULL结束的字符串的前n个字节复制到dest所指的数组中。

说明:

如果src的前n个字节不含NULL字符,则结果不会以NULL字符结束。  

如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节。src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。  

返回指向dest的指针。  

举例:  

//   strncpy.c  

#include   <syslib.h>  

#include   <string.h>   

main()  

{  

char   *s="Golden   Global   View";  

char   *d="Hello,   GGV   Programmers";  

char   *p=strdup(s);  

clrscr();  

textmode(0x00);     //   enable   6   lines   mode  

strncpy(d,s,strlen(s));  

printf("%s/n",d);  

strncpy(p,s,strlen(d));  

printf("%s",p);  

getchar();  

return   0;  

}  

2>memcpy    

原型:extern   void   *memcpy(void   *dest,   void   *src,   unsigned   int   count);  

用法:#include   <string.h>  

功能:由src所指内存区域复制count个字节到dest所指内存区域。  

说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。  

举例:  

//   memcpy.c  

#include   <syslib.h>  

#include   <string.h>  

main()  

{  

char   *s="Golden   Global   View";  

char   d[20];  

clrscr();  

memcpy(d,s,strlen(s));  

d[strlen(s)]=0;  

printf("%s",d);  

getchar();  

return   0;  

}  

 


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值