该程序接受一个指向char数组的指针和一个int.字符数组由两个用空格分隔的数字组成.

该函数的用法是将char数组的值读取为int‘s,并用输入的相乘的值替换它们:

void read_and_mul(char * arr,int scale) {
    int num_arr[2];                         // saving values in a int[]
    char * ch = strtok(arr," ");
    num_arr[0] = scale * (atoi(ch));
    ch = strtok(NULL," ");
    num_arr[1] = scale * (atoi(ch));

    memset(arr,0,sizeof(arr));      // deleting the previous value of the char[]

    char one[sizeof (int)];
    char two[sizeof (int)];
    sprintf(one,"%d",num_arr[0]);   // saving the altered numbers as chars
    sprintf(two,"%d",num_arr[1]);

    strcat(arr,one);                // writing the multiplied values to the string
    strcat(arr, " ");
    strcat(arr,two);
}

无论如何,我这样使用它,它按预期工作,但会导致堆栈崩溃:

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

    char str[] = "1 2";
    read_and_mul((char *) &str, 10);
    printf("string after call: %s\n",str);

    return 0;
}

Clion中的终端消息为:

*** stack smashing detected ***: terminated
string after call: 10 20

这是一个潜在的错误还是ide警告,是什么导致的?

推荐答案

该函数必须构建包含6个字符的字符串"10 20",该6个字符包括终止空字符'\0'.

但是您正在try 将该字符串存储在一个只有4个字符的数组中

char str[] = "1 2";

由于这些声明

strcat(arr,one);                // writing the multiplied values to the string
strcat(arr, " ");
strcat(arr,two);

因此,该函数已经调用了未定义的行为.

另一个问题是在这个memset人的电话中:

memset(arr,0,sizeof(arr));

函数内的变量arr具有指针类型char *.如果sizeof( char * )等于8,则再次try 写入数组外部的存储器.

并且该函数不应依赖于此声明中使用的幻数(如2

int num_arr[2];

您应该始终try 编写更通用的函数.

要解决这个问题,您应该在函数内动态分配一个新的字符数组来存储结果字符串,并从函数返回指向该数组的指针.

另外,请注意,这样写起来会更清楚和正确

read_and_mul( str, 10 );

而不是

read_and_mul((char *) &str, 10);

下面是一个演示程序,它展示了一种解决该任务的可能方法.

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

char * read_and_mul( const char *s, int scale )
{
    size_t n = 0;
    size_t length = 0;

    const char *tmp = s;
    int value;

    for (char *endptr; value = strtol( tmp, &endptr, 10 ), endptr != tmp; tmp = endptr)
    {
        ++n;
        length += snprintf( NULL, 0, "%d", value * scale );
    }

    length += n == 0 ? 1 : n;

    char *result = calloc( length, sizeof( char ) );

    if (result != NULL)
    {
        const char *tmp = s;
        int first = 1;

        for (char *pos = result, *endptr; value = strtol( tmp, &endptr, 10 ), endptr != tmp; tmp = endptr)
        {
            if (!first)
            {
                *pos++ = ' ';
            }
            else
            {
                first = 0;
            }

            pos += sprintf( pos, "%d", value * scale );
        }
    }

    return result;
}

int main( void )
{
    char s[] = "1 2 3 4 5 6 7 8 9 10";

    char *result = read_and_mul( s, 10 );

    if (result) printf( "\"%s\"\n", result);

    free( result );
}

程序输出为

"10 20 30 40 50 60 70 80 90 100"

因为通常情况下,两个整数的乘法可能会导致溢出,为了避免这种情况,您可以更改以下语句

length += snprintf( NULL, 0, "%d", value * scale );
pos += sprintf( pos, "%d", value * scale );

至以下各项

length += snprintf( NULL, 0, "%lld", ( long long int )value * scale );
pos += sprintf( pos, "%lld", ( long long int )value * scale );

C++相关问答推荐

segfault在C中使用getline()函数

在C语言中使用scanf()时我无法理解的警告

C语言中字符数组声明中的标准

手动矢量化性能差异较大

为什么可以通过指向常量int的指针间接地改变整数的值?

C:二进制搜索和二进制插入

当我运行/调试C程序时,Malloc()似乎正在将&q;r\r...&q;赋值给一个指针,我不确定为什么?

将fget()与strcMP()一起使用不是正确的比较

C是否用0填充多维数组的其余部分?

当我更改编译优化时,相同的C代码以不同的方式运行

使用错误的命令执行程序

将回调/基于事件的C API转换为非回调API

从BIOS(8086)中读取刻度需要多少?

C++中PUTS函数的返回值

如何修复我的qsort()算法?它每次都给出不同的结果

Linux/C:带有子进程的进程在添加waitid后都挂起

当我将偏移量更改为任何非零值时,C中的mmap共享内存出现无效参数错误

`%%的sscanf无法按预期工作

If语句默认为true

nullptr_t 是否会 destruct 类型双关或指针转换?