首页 > 试题广场 >

以下函数用法正确的个数是:

[单选题]

以下函数用法正确的个数是:

void test1(){
    unsigned char array[MAX_CHAR+1],i;
    for(i = 0;i <= MAX_CHAR;i++){
        array[i] = i;
    }
}
char*test2(){
    char p[] = "hello world";
    return p;
}
char *p = test2();
void test3(){
    char str[10];
    str++;
    *str = '0';
}
  • 0
  • 1
  • 2
  • 3
推荐
第一个问题:
重点不在于CHAR_MAX的取值是多少,而是在于i的取值范围是多少。
一般char的取值范围是-128到127,而u char 则是0~255,所以i的取值范围是0~255.
所以当CHAR_MAX常量大于255时,执行i++后,i不能表示256以上的数字,所以导致无限循环。
第二个问题:
重点在于函数中p的身份,他是一个指针,还是数组名;

如果是指针p,则p指向存放字符串常量的地址,返回p则是返回字符串常量地址值,调用函数结束字符串常量不会消失(是常量)。所以返回常量的地址不会出错。
如果是数组p,则函数会将字符串常量的字符逐个复制到p数组里面,返回p则是返回数组p,但是调用函数结束后p被销毁,里面的元素不存在了。
例子中p是数组名,所以会出错,p所指的地址是随机值。
若是把char p[]="hello";改成char *p="hello";就可以了。
第三个问题:
重点在于str++;这实际的语句就是str=str+1;而str是数组名,数组名是常量,所以不能给常量赋值。(可以执行str+1,但是不能str=.)
编辑于 2016-02-18 16:09:01 回复(25)
    char  str[10];
    str++;
是错误的。
因为这里的str 是一个常量指针,不能进行左值操作。【但是可以使用sizeof】
对比char* str1 = "hello";
    char  str2[] = "hello";
str1 是指向首元素的指针,可以修改;
str2 是一个指向数组的常量指针;
编辑于 2015-08-11 12:03:02 回复(3)
贴一个百度知道的回答,我觉得讲的还不错。

c语言 char *str 与char str[] 这俩种定义字符串到底有什么区别

楼上说的都有道理,但是没解释出本质区别。
区别就在于两个定义中str的类型不同。

第一个,在
char * str;
中,明显str的类型是char*。这没什么特殊的,只是一个简单的char指针。

第二个,char str[];是不能这样定义的,所以假定用
char str[6] = "abcde";
那么这里str的类型是char[6](6个,不是5个,因为最后有个0) ,而这种定义语句也是定义一个char[6]类型的唯一方法。char[6]是什么意思呢?他不是char*,也不是char* const (以下讨论这个),而是一个特殊的类。这个类的大小是6字节(比如sizeof(str)返回6),它可以用[ ]来返回一个char&(比如str[3]的类型是char&),但是自身不能直接被修改,比如str ="abcde";就不可以。

我刚才说char[6]很像char* const。这是因为,假如有
char* const str2 = "abcde";
那么str和str基本有同样的行为,比如str2[3]也是一个char&,而且str2 = "abcde"也不可以用,但是char* const和char[6]有本质的不同。前者只是一个指针。什么意思呢,就是str2的值是"abcde"的地址(而"abcde"被存在其他的地方),而str的内存值直接就是6个字节,"abcde"。所以两者还是截然不同的类型。比如,sizeof(str2)是4(32位操作系统)或8(64位),而sizeof(str)是6.  

char[6]可以被直接转换为char*。转换的时候,得到的结果是一个指向第一个元素的指针。反过来,char*也可以转换为char[6],转换的结果是一个变量指向char*所指向的那个内存区域。

楼上说的str++可以在char* str时用而不能在char str[6]时用,这是因为数组类型 char[6]不能用作一个左值。

楼上还有说char * str可以指向任何字符串常量。这个是无必要的。char *可以指向任何内存区域,不一定必须是字符串常量。当然,如果指向一个无效内存,用的时候会出问题。

另外楼上说一个"Hello World!"放在常量储存区,一个"Hello World!"放在线程堆栈区,这也是不对的。事实上,无论如何,"Hello World!"本身都在常量储存区。而:
char *str = "Hello World!";
会在堆栈上储存一个4个字节(假定32位系统)的指针指向储存"Hello World!"的区域。
而
char str[] = "Hello World!";
会首先在堆栈上先分配一个13字节的char数组,然后把常量储存区的那个"Hello World!"复制过来。

发表于 2018-07-05 12:34:02 回复(1)
我觉得一个也不对,第一个死循环,除非MAX_CHAR的值小于255,第二个函数栈中使用完成后,函数调用完成会被系统回收,第三个当然不对,第四个,是个常量指针不能进行操作。
发表于 2015-08-10 12:07:24 回复(1)
第二个函数:
如果是指针p,则p指向存放字符串常量的地址,返回p则是返回字符串常量地址值,调用函数结束字符串常量不会消失(是常量)。所以返回常量的地址不会出错。
如果是数组p,则函数会将字符串常量的字符逐个复制到p数组里面,返回p则是返回数组p,但是调用函数结束后p被销毁,里面的元素不存在了。
发表于 2016-05-23 20:43:21 回复(0)
test1: unsigned char是无符号字符型,可输入的范围是[0~255],当MAX_CHAR的值大于255时,for循环即无法跳出,陷入死循环。重复0-255。 test2: 函数被调用后,它的内部创建的数组,变量等会随着函数体的结束而销毁,P会指向一段无效的空间。 test3: 数组名是常量,它的值不能被改变。
发表于 2022-04-08 12:37:39 回复(0)
1.会导致无限循环
2.不能返回局部变量的地址
3.数组名是地址常量,不可进行运算。
发表于 2021-03-14 10:15:56 回复(0)
(1), i的值不会超过MAX_CHAR,到了255 就会又从0开始;(2)char p[] 是个栈上的数组,函数弹栈就没了,返回地址所指内容无法预知;(3)数组名,不是左值
发表于 2018-03-15 18:43:45 回复(0)
1.数组名为常量,不能被赋值。 2.函数返回值不能是内部定义的数组名,可以为指针和变量。
发表于 2017-02-19 00:55:18 回复(0)
函数1当i超过255之后又从0开始,所以会变成无限循环
函数2不能返回栈上的空间
函数3数组名为常量,不能执行++运算,但是可以执行+1运算
发表于 2016-10-13 20:57:38 回复(0)
第一个错误的地方:当MAX_CHAR大于255时,将大于unsigned char最大范围的赋值给它会出错;
第二个函数错误的地方:返回数组p的名称时自动转换为指向数组第一个元素的指针,在VS2013中test2会有警告说返回了局部变量的指针,但是仍然可以运行。
第三个函数中str++是非法的,会提示左值不可修改,数组只在作为右值赋值给指针时才会转化为指向第一个元素的指针。
发表于 2015-11-12 11:18:45 回复(0)
指针指向的字符串,是指向常量中的地址,p[] = "' 是将常量地址中的字符串复制过来,所以外界指针指向此数组的地址,一但出栈,就会销毁数组空间。
发表于 2015-09-15 15:19:37 回复(0)
只有函数2错误 :
        p[]是在栈上开辟的临时数组变量,在函数执行完毕时被释放,把他的地址返回是毫无意义的 ,在外部使用这个指针只会出现段错误
函数1,3正确,故选C
发表于 2015-08-09 17:07:19 回复(0)
test1 是个死循环 ! test2的局部变量p存放在栈上面,返回时,地址已经被系统回收。()第三个test3绝对会报错,str++;数组名为常量指针,不可能会被改变的。
发表于 2015-08-09 13:26:02 回复(1)
第三个test3绝对会报错,str++;数组名为常量指针,不可能会被改变的。test2的局部变量p存放在栈上面,返回时,地址已经被系统回收,用作他用。
虽然说语法不会报错,但是这绝对是不合理的。我选B,因为test2函数用法不正确。
发表于 2015-08-09 12:38:01 回复(0)

第二题:那个p数组的数组名p,不是等于该数组的首地址吗?将他返回不是等于返回数组首地址?

第三题:同样的,第三题的str作为数组,不是可以对str这个数组名进行++吗?相当于地址加一?


发表于 2019-03-18 23:58:26 回复(1)
都不对。
第一处,i的取值范围是[o, MAX_CHAR],当取MAX_CHAR时,数组越界。
第二处,返回的指针p是在函数内部开辟空间的,函数结束后,p指向的内存空间自动回收,调用test2()返回的指针已经被回收。
第三处,不能对数组名进行修改操作,数组名为常量指针。
发表于 2015-08-12 12:20:46 回复(2)
第二个错没啥说的  第三个亲测  报错  其实第一个 函数是没啥问题 但是如果[MAX_CHAR很大的话  i会越界  
发表于 2015-08-09 23:28:14 回复(0)
第一个问题,uchar型一般是0到255,int型也是0到255,超过255次就会无限循环
发表于 2021-01-12 07:02:24 回复(0)
第一个,MAX_CHAR没有定义;
第二个,应改为static  charp[] = "hello world",数组位于静态存储区,可通过函数返回;
第三个,数组的首地址是常量,不可变更,str++错误
发表于 2015-08-14 20:11:57 回复(0)

1.unsigned char取值范围为0-255,如果MAX_CHAR大于255的话,i大于255,会再次返回0,导致死循环
2.p是一个局部变量,是一个字符数组,局部变量在栈上,返回p的地址之后,p原来指向的字符数组,在栈上的内存已被释放,如果函数返回后再访问的话,会报访问非法地址的错误。
注意:这里区分

char* p = "hello world";
char p[] = "hello world";

二者的区别。
(1)
首先,"hello world"是一个无名的字符串常量,也就是const char*类型,常量在程序运行过程中,保存在数据段里面,其生命周期随着程序的结束而结束。而p是一个局部变量,保存在栈上,随着函数的返回而销毁。
(2)

char* test2()
{
    char* p = "hello world";
    return p;
}

这里定义一个char*类型的局部变量p,然后再将const char*类型的字符串常量赋值给p,然后将p的值通过函数返回值返回。
再在main函数中访问的时候,虽然局部变量p已经销毁了,但是p的值通过函数返回值传递了过来,并且其值是一个指针,所指向的区域是"hello world"这个字符串常量的存储区域,不会随着局部函数的返回而销毁,因此可以访问。
(3)

char* test2()
{
    char p[] = "hello world";
    return p;
}

此时char p[] = "hello world"这句话的本质是一个字符数组的初始化操作。这里的局部变量p会开辟一个新的地址内存区域,来保存字符数组,然后再将该数组的首地址返回。这里虽然可以返回p的地址,但是局部变量p所指向的内存区域会随着函数的返回而销毁。因此在main函数中即使得到了之前局部变量p的地址,其对应的字符数组的内存区域已经销毁,对其进行访问的话会报Segmentation fault (core dumped)段错误,访问非法地址。

可以运行下面这个程序,在函数的局部作用域内,将地址打印出来就一目了然了

#include <stdio.h>
char* test2()
{
    char* p1 = "hello world";
    char p2[] = "hello world";
    printf("%x\n", "hello world");//845bc008
    printf("%x\n", p1);//845bc008
    printf("%x\n", p2);//6a2423bc
    return p1;
//  return p2;//返回p2会造成段错误
}

int main(int argc, char *argv[])
{
    char* p = test2();
    printf("%s\n", p);
}

3.数组名str是一个指针常量,不能作为左值,以及进行自增自减操作。

发表于 2023-10-21 11:16:04 回复(0)