Платформа: Win11, VisualStudio 2022. Код:
#include <stdio.h>
#include <string.h>
int main()
{
char ori[5] = { 'a', 'b', '\0', 'c', 'd' };
//char *safe = malloc(10 * sizeof(char));
//char *unsafe = malloc(10 * sizeof(char));
char safe[10];
char unsafe[10];
memset(safe, 0, 10 * sizeof(char));
memset(unsafe, 0, 10 * sizeof(char));
strcpy(unsafe, ori);
strcpy_s(safe, 10, ori);
printf("SAFE: %c\n", safe[3]);
printf("UnSafe: %c\n", unsafe[3]);
return 0;
}
У меня есть два массива, safe и unsafe. После memset оба они инициализируются как {0,0,0,0,0,0,0,0,0,0} (показывая символы как целые числа).
После strcpy и strcpy_s я ожидаю получить {'a','b','\0','\0','\0','\0','\0','\0','\0','\0'} в обоих массивах safe и unsafe. Однако в safe я получил {97,98,0,-2,-2,-2,-2,-2,-2,-2} (показывая символы как целые числа).
Что делает strcpy_s и откуда берется -2?
Это похоже на C, а не на C++. Зачем вам использовать массивы в стиле C, malloc и strcpy в C++? printf и memset В некоторых случаях я мог бы терпеть, но должна быть действительно веская причина (здесь ее нет).
К вашему сведению: стд::размер.
@JesperJuhl, код на C, и я использовал неправильные теги.
@AndreasWenzel Готово, с c и visual-c++, потому что не найден тег «visual-c»
@ZhouJia: Тег visual-c++ правильный, так как это название продукта. Visual C++ поддерживает как C, так и C++.





официальная документация Microsoft для функции strcpy_s гласит следующее:
Версии этих функций из библиотеки отладки сначала заполняют буфер значением 0xFE. Чтобы отключить это поведение, используйте _CrtSetDebugFillThreshold.
Если вы преобразуете 0xFE в signed char, вы получите значение -2.
std::string или пользовательский буфер, переданный fread())
Написание -2 разрешено спецификацией C.
errno_t strcpy_s(char * restrict s1, rsize_t s1max, const char * restrict s2);
Все элементы, следующие за завершающим нулевым символом (если есть), записанным
strcpy_sв массиве символовs1max, на которые указываетs1, принимают неуказанные значения при возвратеstrcpy_s. C17dr § K.3.7.1.3 4
Это применимо независимо от любых настроек отладки.
Код не должен полагаться на то, что байты после нулевого символа останутся неизменными.
sizeof(char)всегда 1. Лучше писатьmemset(safe, 0, sizeof safe);, потому что вам больше не нужно менять размер при измененииsafe