Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > функция strncpy


Автор: IKM2007 10.5.2008, 09:56
Код

#include <iostream>
using namespace std;
void main()
{
char *a=new char[17];
strncpy(a,"123456789123456789123456789",17);
cout<<a<<endl;
}

Почему на экране появляется более 30-и символов
Цитата

12345678912345678¤¤¤¤▌▌▌▌▌▌▌▌▌▌▌q
Press any key to continue


,если я копирую в массив a 17 символов?
Заранее, Спасибо.

Автор: archimed7592 10.5.2008, 10:00
Потому что ф-ция, в случае неумещения в рамки не добавляет trailing zero. На сайте, который я тебе дал вчера, об этом должно быть написано ;).

Нужно так:
Код

const int arrSize = 17;
char *a=new char[arrSize];
strncpy(a,"123456789123456789123456789", arrSize - 1);
a[arrSize - 1] = '\0';

Т.е. явно убеждаться, обнулять последний элемент массива.

Автор: IKM2007 10.5.2008, 11:53
archimed7592, а почему при cout<<a; печатается окончательное число символов, если нет завершающего символа? smile
И вообще, откуда эти символы беруться???

Автор: bronislav 10.5.2008, 12:40
Я не archimed7592, но отвечу =)

Операторы <<  и >> перегружены для char*, и поэтому такое нармально вводится

Автор: IKM2007 10.5.2008, 12:42
bronislav, можно поподробней.

Автор: W4FhLF 10.5.2008, 12:42
Потому, что в С/С++ признаком конца строки является символ '\0'. При выделении памяти под массив, эта память, в твоём случае, заполняется мусором и когда ты посылаешь данные, расположенные по этому адресу в памяти, на печать в консоль поток вывода печатает все данные, пока не встретит символ '\0'. Теоретически, он может напечатать и миллион ненужных тебе символов, пока встретит символ конца строки. В твоём случае, после "12345678912345678¤¤¤¤▌▌▌▌▌▌▌▌▌▌▌q" в массива оказался нулевой байт и печать прекратилась. 

Автор: MAKCim 10.5.2008, 12:46
Цитата(IKM2007 @  10.5.2008,  11:53 Найти цитируемый пост)
И вообще, откуда эти символы беруться???

из области памяти с начальным адресом a + 17
если брать имплементацию аллокатора в GCC, то по этому адресу скорее всего будет находится блок метаинформации о ранее выделенном блоке памяти

Автор: IKM2007 10.5.2008, 12:50
W4FhLF, Спасибо за исчерпивающий ответ, Премного блогадарен! smile

Добавлено через 4 минуты и 44 секунды
MAKCim, я вообще то пользуюс Visual C++, так что не знаю
Цитата(MAKCim @  10.5.2008,  12:46 Найти цитируемый пост)
если брать имплементацию аллокатора в GCC, то по этому адресу скорее всего будет находится блок метаинформации о ранее выделенном блоке памяти

но все равно пасиб smile 

Автор: archimed7592 10.5.2008, 15:25
IKM2007, может обратишь уже свой взор в сторону прикреплённой темы http://forum.vingrad.ru/index.php?show_type=articles&showtopic=60932 ? smile 

Автор: lp_sun 10.5.2008, 23:40
ребят, помоги заодно и мне вкурить такую фишку:
Код

#include <stdio.h>
#include <conio.h>
#include <string>

int main()
{        
    char pntr_shm[10];
    
    int msg_size=1023; 

    strncpy(pntr_shm,(char*)&msg_size,sizeof(int));
    
    int b;
    strncpy((char*)&b,pntr_shm,sizeof(int));

    printf("%d\n",b);
        
    getch();
    return 0;
}


если msg_size=1023 или 1025 или другие значения то все копируется нормально и в b в результате получаем наше значение, но если в msg_size записать 1024 то в b будет 0. Я так понимаю это связано с тем что под 1024 какой то управляющий символ и strncpy поэтому работает некорректно????? объясните плиз
и тогда подскажите эквивалент какой нить этой функции шоб она просто по указателям опредеоенные блоки памяти копировала 

Автор: archimed7592 11.5.2008, 00:08
lp_sun, во-первых, это зависит от того, чем pntr_shm инициализирован.
Во-вторых, это зависит от endianness - порядка байт в машинном слове.
К примеру, если msg_size=2048, то скорее всего тоже будет b=0.
Объясняется это так.
Если разбить 1024 на байты, то получится следующее: 00 00 04 00. Если записать это дело задом наперёд(как это, скорее всего, хранится в памяти твоего компьютера), то получим 00 04 00 00 - как видишь первым байтом(читай первым символом в строке) будет ноль, а ноль - это признак конца строки, откуда strncpy делает вывод о том, что далее копировать не нужно.
Если, разбить 1025 на байты, то получим 00 00 04 01, что задом наперёд будет 01 04 00 00 - т.е. первые два байта будут скопированны, остальные нет(но они и так нули).
Аналогично 1023: 00 00 03 FF -> FF 03 00 00.

Какой вывод нужно сделать? Такой, что ф-ции str*** предназначены для работы со строками и ни с чем иным. Для работы с raw памятью имеются, к примеру ф-ции mem***.

Добавлено через 50 секунд
Цитата(lp_sun @  10.5.2008,  23:40 Найти цитируемый пост)
и тогда подскажите эквивалент какой нить этой функции шоб она просто по указателям опредеоенные блоки памяти копировала  

memcpy

Автор: lp_sun 11.5.2008, 00:37
archimed7592, благодарю за развернутый ответ smile) все понятно

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)