Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Куда пакуются строки?

55K
28 января 2013 года
kosopet
10 / / 20.04.2010
есть вот такой кусочек на Си:


Код:
#include <stdio.h>

char a[10000][3];

void main() {
    int i,j,n;
    scanf("%d", &n);
    for(i=0;i<n;i++) {
        scanf("%s", &a[i]);
        printf("%s\n", a[i]);
   
        for(j=0;j<=6;j++)
            if(j==6)
                printf("\n");
       
            else
                printf("%c", a[i][j]);
               
    }
}
при этом результат работы этого выглядит вот так:
  • qwertyuiop
  • qwertyuiop
  • qwerty

где первая строчка это то что считывается в scanf, вторая это то что распечатывает printf как строку - %s
и третье это то что распечатывает printf посимвольно.

Почему не действует ограничение в 3 символа на строку (или даже 2 учитывая '\0' в конце строки) ?

Почему-то printf распечатывает a(i) как %s в таком же размере как было считано в scanf. Куда помещаются в таком случае все символы следующие за 3-м, если массив определен как a[10000][3] ?

Также неясно почему не ругается на то что при посимвольной распечатке индекс j превышает размер второго измерения массива 3.
360
28 января 2013 года
P*t*
474 / / 15.02.2007
Для большей понятности выделяйте код тегами [сode] [/сode]


В си вообще нет проверок на выход за границы массива. Считается, что если программист вышел за границы, значит это для чего-то нужно.
Указание char a[10000][3] просто выделит 30000 последовательно расположенных байт памяти. Так что строка до 30000 символов туда влезет. Вот если сильно больше - тогда уже будет обращение к недоступной памяти и программа с некоторой вероятностью ругнется при запуске.

scanf вообще не знает, какого это размера массив, в scanf передается только указатель на начало области для записи строки.
Если нужно считывать не более, чем по 3 символа - попробуйте функцию fgets.
55K
28 января 2013 года
kosopet
10 / / 20.04.2010
а разница адресов a(i) и a(i+1) элементов массива разве не равна трём ?
360
28 января 2013 года
P*t*
474 / / 15.02.2007
Цитата: kosopet
а разница адресов a(i) и a(i+1) элементов массива разве не равна трём ?



Да, равна 3-м.
Но из за отсутствия проверок на выход за границы массива будут эквивалентны записи: a[0][10] = a[1][7] = a[2][4] = a[3][1]

55K
29 января 2013 года
kosopet
10 / / 20.04.2010
Вот посмотрите, такой вот код:

Код:
#include <stdio.h>


char a[10000][3];


void main()     {


int i,j,n;


scanf("%d", &n);


for(i=0;i<n;i++)        {

       
        scanf("%s", &a[i]);
       
        printf("%s(%X)\n", a[i],&a[i]);
       
        for(j=0;j<=3;j++)
                if(j==3)
                        printf("\n");
                else
                        printf("%c(%X)", a[i][j],&a[i][j]);


        }


}

Результат работы программы при n=2:



2
qwertyuiop
qwertyuiop(804A040)
q(804A040)w(804A041)e(804A042)
zxcvbnm
zxcvbnm(804A043)
z(804A043)x(804A044)c(804A045)





Вопрос - по каким адресам записаны символы введенных строк, начиная с четвертого символа ?
360
29 января 2013 года
P*t*
474 / / 15.02.2007
Цитата: kosopet

Вопрос - по каким адресам записаны символы введенных строк, начиная с четвертого символа ?



Чтобы это узнать достаточно сделать цикл вывода символов не до 3-х, а побольше.

Будет что-то такое:
2
qwertyuiop
qwertyuiop(804A040)
q(804A040)w(804A041)e(804A042)r(804A043)t(804A044)
zxcvbnm
zxcvbnm(804A043)
z(804A043)x(804A044)c(804A045)b(804A046)n(804A047)

Это значит, что вторая строка затерла собой конец первой.
Команда printf("%s(%X)\n", a[0],&a[0]); после этого выдаст qwezxcvbnm(804A040)

55K
29 января 2013 года
kosopet
10 / / 20.04.2010
да затирают действительно, ...просто мне почему-то казалось что как раз таки строки сохраняются в целости,
после заполнения массива.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог