Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.54/107: Рейтинг темы: голосов - 107, средняя оценка - 4.54
655 / 576 / 164
Регистрация: 13.12.2012
Сообщений: 2,126

В чем разница между char* и char[]?

01.10.2014, 18:28. Показов 23461. Ответов 69
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток, наткнулся на одну загвоздку есть такой кусок кода
C++
1
2
3
4
5
6
7
8
int _tmain(int argc, _TCHAR* argv[])
{
    char *a = "111111111111";
    *((int*)a+1) = 0;
    std::cout<<a;
    system("pause");
    return 0;
}
и такой
C++
1
2
3
4
5
6
7
8
int _tmain(int argc, _TCHAR* argv[])
{
    char a[] = "111111111111";
    *((int*)a+1) = 0;
    std::cout<<a;
    system("pause");
    return 0;
}
запускаем в виже, первый кусок эксепшн
второй норм. Разъясните пожалуйста
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
01.10.2014, 18:28
Ответы с готовыми решениями:

В чем разница между char* и char **
в чем разница между char* и char ** ??

Разница между char и signed char
Не понимаю в чем разница между char и signed char, ведь char по умолчанию знаковый. Не комплилируется следующий фрагмент кода: void...

Разница между char[] и char*
Здравствуйте. Провожу небольшую иследовательскую работу по выяснении разницы между char и char*. Пришел к логическому выводу, что char*...

69
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21282 / 8307 / 637
Регистрация: 30.03.2009
Сообщений: 22,668
Записей в блоге: 30
02.10.2014, 19:00
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от IGPIGP Посмотреть сообщение
И кто был прав? Строго говоря, - оба (имхо). Это место в языке достаточно противоречиво
На самом деле не правы оба. Потому что указатель он ни на что (разве что на тип), а просто адрес.

C
#include <stdio.h>
 
void func (char *p)
{
  p[-2] = 'a';
  p[-1] = 'b';
  p[0] = 'c';
  p[1] = 'd';
  p[2] = '\0';
}
 
int main (void)
{
  char c[5];
  func (&c[2]);
  printf ("%s\n", c);
  return 0;
}
И в стандарте никаких противоречий нет, потому что указатель является указателем на тип (т.е. типизированным адресом), а не указателем на одну штуку экземпляра типа и не на массив экземпляров типа
2
Модератор
Эксперт С++
 Аватар для zss
13789 / 10981 / 6492
Регистрация: 18.12.2011
Сообщений: 29,281
02.10.2014, 19:01
Эта ошибка рассмотрена в
Распространенные ошибки
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21282 / 8307 / 637
Регистрация: 30.03.2009
Сообщений: 22,668
Записей в блоге: 30
02.10.2014, 19:02
А типизация адреса нужна исключительно для того, чтобы знать, как с этим указателем работать: сколько байт читать/писать за одно обращение к указателю и на сколько байт сдвигать значение в арифметических операциях
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
02.10.2014, 20:25
Цитата Сообщение от Evg Посмотреть сообщение
И в стандарте никаких противоречий нет, потому что указатель является указателем на тип
Тип может быть параметром шаблона, но не переменной же. Типизированный адрес, - согласен. Я не спорю с указателем на тип, как с термином принятым в документации, но семантически это указатель на объект. Даже если его там нет или там что-то другое. Для char как атома адресации, это буквально, - указатель на символ - байт. В простом целом их 4 на 32-разрядной машине и указав на него чаром можно получить первый после разадресации.
Но все типы с перегруженными [] обладают признаком массива. В случае с указателями эта двоякость ещё и подтверждается семантикой: - доступ к элементам одного типа расположенных последовательно... (статические строки и табличную оптимизации не рассматриваем).
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21282 / 8307 / 637
Регистрация: 30.03.2009
Сообщений: 22,668
Записей в блоге: 30
02.10.2014, 20:47
Цитата Сообщение от IGPIGP Посмотреть сообщение
но семантически это указатель на объект
C
int*
foo (int *p)
{
  p++;
  return p;
}
 
void bar (void)
{
  long addr1, addr2;
  addr1 = 0;
  addr2 = (long) foo ((int*) addr1);
}
Здесь указатель в функции foo не является указателем на объект. Но ведь указатель вовсе необязательно разыменовывать, над ним можно арифметику проводить
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
02.10.2014, 21:02
Цитата Сообщение от quwy Посмотреть сообщение
В первом случае a -- указатель, а во втором -- массив. Поэтому обращаться к ним нужно по-разному.
Нет. В первом случае указатель, во втором массив. И именно поэтому обращаться к ним надо одинаково. Фокус в том, что на c++ массивы реализуются на указателях.
C++
1
a[i]
- синоним
C++
1
*(a+i)
. При этом не имеет значения, как именно объявлено a и имеет ли вообще какое либо отношение к чару. При адресации элемента массив есть указатель, с точки зрения sizeof массив и указатель различны, к линейному массиву-параметру это не относится, такой массив - лишь синтаксическая обёртка над указателем, но параметр, являющий массивом массивов с точки зрения sizeof отличен от указателя, массив нельзя явно освобождать и явно выделять по нему память и опять таки это не относится к линейным массивам-параметрам.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21282 / 8307 / 637
Регистрация: 30.03.2009
Сообщений: 22,668
Записей в блоге: 30
02.10.2014, 21:03
Хотя, я разогнался. По стандарту поинтерные операции определены когда указатели смотрят вовнутрь одного и того же объекта. Т.е. педантично мой пример не корректкен, но в реальной жизни он будет работать вполне конкретным образом
1
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
02.10.2014, 21:45
Цитата Сообщение от Evg Посмотреть сообщение
Здесь указатель в функции foo не является указателем на объект.
Я говорил не о том, есть ли там объект и можно ли интерпретировать то, что там есть в действительности как объект типа. Указатель об этом не знает по определению, он предоставляет (пытается представить) то на что указывает как объект цепочку данных определённой длины и умывает руки. Я о том и говорил, что тут легко можно спорить и спорить. А можно согласиться.

Добавлено через 10 минут
Цитата Сообщение от taras atavin Посмотреть сообщение
Фокус в том, что на c++ массивы реализуются на указателях.
Верно. Но все переменные где-то имеют адрес, который как-то хранится. Мы говорим (глядя в заголовок темы), о том что указатели, массивы и указатели на массивы, тем более, это разные вещи.
Цитата Сообщение от taras atavin Посмотреть сообщение
При этом не имеет значения, как именно объявлено a и имеет ли вообще какое либо отношение к чару.
Опять же топик. Указатели на char, как и любые указатели имеют оператор [], то есть созданы по-эррейски, но указатели на char имеют слишком много особенностей, что бы их не замечать. В частности, в каком-то смысле они, - прародители всех эрреев. Эррей любого типа всегда можно рассыпать на эррэй char, но не наоборот, например.
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
03.10.2014, 06:51
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class A
{
 public:
  double x,y,z;
  A();
  A(const A &a);
 ~A();
 A operator +(const &A a);
 A operator - (const &A a);
 A operator *(double a);
 A operator / (double a);
};
...
char *c=new char [2412];
A *a=(A*)((void*)c);
. Что здесь не так? Возможность получить недопустимые значения не исключает приведение, по Вашей же логике и на чары ничего не рассыпается, так как полученные чары бессмысленны и им могут не соответствовать ни какие экранные символы.

Добавлено через 1 минуту
Цитата Сообщение от IGPIGP Посмотреть сообщение
Верно. Но все переменные где-то имеют адрес, который как-то хранится.
C++
1
2
3
4
A a[256];
A *p=a; // допустимо
A b;
A *q=b; // Ошибка времени компиляции
. Потому что адреса переменных валяются прямо в коде, адрес же массива - это данное, которое можно присвоить другому данному, а потом перебирать в цикле, инкремируя адрес вместо того, чтоб при каждом обращении к элементу вычислять адрес элемента. На паскале не так, там массив указателю не присваивается и указатели для перебора элементов массива не предназначены.

Добавлено через 5 минут
Это особенность именно языка си и его потомков.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
03.10.2014, 13:51
Цитата Сообщение от taras atavin Посмотреть сообщение
по Вашей же логике и на чары ничего не рассыпается, так как полученные чары бессмысленны и им могут не соответствовать ни какие экранные символы.
Мы говорим разно об одном. char это вообще не экранный символ, это байт. Соответствие начертания в кодировке ищется как возможная интерпретация. Но когда, например:
C++
1
2
3
4
5
6
7
class A{
//*********
};
 
//***************
char *place_A_ptr = new char[sizeof(A)];
A *built_A_at_place = new(place_A_ptr ) A;
не предполагается никакой "'экранной" интерпретации. Беда в том, что мы часто подменяем char-байт/символ, экранным символом, и как следствие char[] - массив/машинная строка, си-строкой совершенно непреднамеренно по крайней мере в терминологии. Новички читая это балдеют.
А на чары можно рассыпать любой тип, так как точнее уже некуда. И подготовить память под него тоже. Разве нет? Но дело вообще не в этом. Главная особенность в том же что множество библиотек без которых язык беспомощен, работают с указателями на char как с указателями на строку. Поэтому например, печать самого чар-указателя на экран и печать указателя на целое выводят разные вещи.
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
03.10.2014, 14:05
Цитата Сообщение от IGPIGP Посмотреть сообщение
Мы говорим разно об одном. char это вообще не экранный символ, это байт.
Ну ка что выведет
C++
1
2
char c=65;
std::cout<<c;
? Бувку А? Неужели? И с каких это пор она стала байтом? char - это именно символ, а в некоторых языках есть и char, и отдельно byte.
Pascal
1
2
3
4
5
6
7
var c:char;
b:BYTE;
begin
c:='A';
b:=65;
writeln(c);{выведет букву}
writeln(b);{выведет число}
. То, что для хранения символа отведён один байт, сути не меняет.

Добавлено через 3 минуты
Уж если
Цитата Сообщение от IGPIGP Посмотреть сообщение
не предполагается никакой "'экранной" интерпретации.
, то
C++
1
2
3
4
5
6
7
class A{
//*********
};
 
//***************
uint8_t *place_A_ptr = new uint8_t[sizeof(A)];
A *built_A_at_place = new(place_A_ptr ) A;
.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
03.10.2014, 15:23
Цитата Сообщение от taras atavin Посмотреть сообщение
Ну ка что выведет
то что должен.
C++
1
2
uint8_t *place_A_ptr = new uint8_t[sizeof(A)];
A *built_A_at_place = new(place_A_ptr ) A
Если вы собрались работать с отдельными байтами класса как с целыми без знака то да. Иначе значения не имеет. Можно любой кусок памяти выделить как char и прочесть как char и даже скопировать как char и вреда не должно быть, несмотря на знаковость char. Вообще всё это уже не по теме.
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
03.10.2014, 16:00
Дело не в знаковости, а во встроенной интерпретации. То, что char совмещает роль кода символа, сути меняет. Самим символом он при это остаётся. Этим char отличается от сырого байта.
0
655 / 576 / 164
Регистрация: 13.12.2012
Сообщений: 2,126
03.10.2014, 16:31  [ТС]

Не по теме:

байт 8 бит? 8, char 8 бит? восемь, значит char это байт, и нефиг спорить, просто эти типы интерпретируются по-разному



Добавлено через 1 минуту

Не по теме:

тоже самое как signed и unsigned, просто меняет интерпретацию старшего бита, оба имеют один размер, оба взаимозаменяемы, одна результаты вычислений будут давать разные...

1
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
03.10.2014, 16:40
Цитата Сообщение от aLarman Посмотреть сообщение
байт 8 бит? 8, char 8 бит? восемь, значит char это байт, и нефиг спорить, просто эти типы интерпретируются по-разному
На паскале byte и char тоже оба по 8 бит. Но чару присваиваются только символы, а байту только числа. И write/writeln выводит в одном случае символ, в другом числа. read/readln в char не может ввести многозначное число. Цифру можно ввести, а даже двузначное нет. В byte отлично вводятся трёхзначные числа теми же read/readln, а буквы, пробел и знаки препинания туда не вводятся. На плюсах тоже
C++
1
2
3
4
5
int a;
char c;
std::cin>>c;
a=c;
std::cout<<a;
при вводе 2 выведет 50.
C++
1
2
3
4
5
int a;
unsigned char c;
std::cin>>c;
a=c;
std::cout<<a;
выведет 50 при том же вводе. Если бы это был сырой байт, то вывелось бы 2. Почему то uint8_t ведёт себя также. Тип - это не только разрядность, int и float тоже одного размера.
0
03.10.2014, 16:46  [ТС]

Не по теме:

Цитата Сообщение от aLarman Посмотреть сообщение
просто эти типы интерпретируются по-разному
повторюсь

0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
03.10.2014, 17:11
Цитата Сообщение от taras atavin Посмотреть сообщение
Почему то uint8_t ведёт себя также.
потому что это обычный typedef на unsigned char в данном случае.
Если нужно выводить char как число, то его нужно приводить к числу. static_cast<int> например.
Иначе как будет выбираться перегруженный оператор << для std::ostream ?

В сях тоже тип надо задавать в строке формата:
C
1
2
3
char c = 50;
printf( "%d\n", c ); // 50
printf( "%c\n", c ); // '2'
1
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
03.10.2014, 17:21
Вывод такой: в c++ вообще нет сырого байта. В этом языке есть символ, кодированный байтом и зовут его char. А сырого байта нет.
0
03.10.2014, 17:32

Не по теме:

Цитата Сообщение от taras atavin Посмотреть сообщение
сырого байта нет
Дык тут нет сыробайтных. Не едим сырого байта. :pardon:
Char'еный байт не хуже var'еного. На мой вкус, даже лучше. (имхо) :pardon:
Системщикам, - срочно учить Паскаль! Там есть сырые первородные байты! И их можно есть. 8-)

0
1406 / 648 / 135
Регистрация: 11.08.2011
Сообщений: 2,299
Записей в блоге: 2
03.10.2014, 18:34
Вот какие гарантии даются относительно типов:
https://www.cyberforum.ru/cgi-bin/latex.cgi?1 \equiv sizeof (char) \leq sizeof (short) \leq sizeof (int) \leq sizeof (long)
https://www.cyberforum.ru/cgi-bin/latex.cgi?1 \leq sizeof (bool) \leq sizeof (long)
https://www.cyberforum.ru/cgi-bin/latex.cgi?sizeof (char) \leq sizeof (wchar_t) \leq sizeof (long)
https://www.cyberforum.ru/cgi-bin/latex.cgi?sizeof (float) \leq sizeof (double) \leq sizeof (long double)
https://www.cyberforum.ru/cgi-bin/latex.cgi?sizeof (N) \equiv sizeof(signed N) \equiv sizeof (unsigned N)
Кроме того, гарантируется что под char будет выделено МИНИМУМ 8 бит, int - минимум 16, long - минимум 32.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
03.10.2014, 18:34

Разница между new char[] и new char[]()
Доброго времени суток. Подскажите пожалуйста разницу, между следующим кодом: char* ch = new char; и char* ch = new...

(char)xx и '\xx' - в чём разница?
День добрый. Просто любопытно, почему cout &lt;&lt; (char)число; и cout &lt;&lt; '\число'; часто дают разный результат?

Разница между char и int
Известно что для чар выделяется 1 байт (8 бит) для инт 4 байта (32 бита). Так почему нельзя в чар присвоить 10 и больше до 255 в виде...

Строка: чем отличается строки string, char, char*?
Помогите разобраться,совсем плохо идёт,чем отличается строки string,char,char* И если можно пару примеров Буду весьма признательна

Чем отличается const char* от char*?
Доброго всем дня! Из матчасти я понимаю, что char* - это указатель массив символов, тогда как const char* - это константный указатель на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
Создание формы заимствованного документа
Maks 03.08.2026
Задача: Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также табличная часть со следующими реквизитами: - Расчетный счет покупателя. . .
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача: В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов. Логика кажется понятной: 1. Находим ключевые слова. 2. Добавляем их на. . .
Знание — сила: Доктрина интенциональности знаний, углубление в формулу
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302 Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru