Странно, зачем вообще разрешать этому фрагменту компилироваться? Ну да ладно.
char* symbolArrayNoSize = new char[];
cout << symbolArrayNoSize << endl;Имеем массив символов неопределённого размера. В результате отображения на экране скорее всего будет выводиться весь хлам до первого символа '\0'. Запуск фрагмента подтвердил предположение:
¤¤¤¤ллллллллю■ю■Предлагаю вашему вниманию следующий фрагмент:
const int ARRAY_LENGTH = 5;
char* symbolArray = new char[ARRAY_LENGTH];
strncpy(symbolArray, "abcdefghijklmnop", ARRAY_LENGTH);
cout << symbolArray << endl;Казалось бы, здесь всё по фэн-шую: размер массива задали, в него скопировали именно необходимое количество символов и вывели на экран. Не тут-то было:
abcde¤¤¤¤иR╕ЧиRШ¤¤¤¤Из этого результата один прискорбный вывод: задаёшь размер массива явным образом - всё равно содержимое будет выводиться до первого встречного '\0'. Так спрашивается, какого хрена задавать размер массива, если он всё равно сомнительную роль играет? Где логика-то?
const int ARRAY_LENGTH = 5;
char* symbolArray = new char[ARRAY_LENGTH + 1];
// Length of useful data is ARRAY_LENGTH plus 1 symbol '\0',// meaning the end of the string.
symbolArray[ARRAY_LENGTH] = '\0';
// Put the delimiter of the string on its proper position
strncpy(symbolArray, "abcdefghijklmnop", ARRAY_LENGTH);
cout << symbolArray << endl;И только в результате вот таких манипуляций получаем ожидаемый результат:
abcdeУдобно? Не очень. Используйте обёрточные классы для С-строк. Не выделывайтесь.
Компилировал в Visual Studio 2010.
Полуночный бред шизофреника))))
ОтветитьУдалить1. Все действия программ абсолютно логичны и правильны.
2. Читаем Википедию, там разжевано до нельзя http://ru.wikipedia.org/wiki/Strncpy
p.s. Как уже говорили, С - мощное оружие, которым легко убиться, если не понимать основных принцип работы. Для остального есть C# :*)
p.s.2. Прежде чем использовать функцию _НЕОБХОДИМО_ всё же прочитать что она делает и _КАК_ она это делает http://www.cplusplus.com/
О, главный критикан пришёл! Думал, когда ж он выползет и начнёт типа "подкалывать"? И он не заставил себя ждать! Но я ж тоже не лыком шит, правда?! Посему наношу ответный удар: ТЫ-ДЫЩ!!! Начинаю огрызаться:
УдалитьГде шизофреники? Галактика опять на моих хрупких плечах? Ахтунг!
13:50 - это ещё не полночь, Дима, ты слегка перепутал.
1. Шо, правда? Ты упал в моих глазах!
Ладно, придётся объяснять неумеющему выделять главное.
Фокус поста в том, что
а) char* symbolArrayNoSize = new char[];
Это компилируется, что само по себе опасно и чревато. Причин использовать такой фрагмент нет. Но ты ж говоришь, что "Все действия программ абсолютно логичны", потому рассказывай, где такое чудо мысли оправдано и логично. Не расскажешь - проиграл по этому пунктику.
б) char* symbolArray = new char[ARRAY_LENGTH];
При попытке отображения symbolArray на экране появляется непредсказуемое кол-во байт содржимого. Смысл тогда в явной длине ARRAY_LENGTH? Дали хотя бы точную длину.
2. Суровым программистам, читающим Википедию, рекомендую бегло ознакомиться с документальной киношкой "Truth in Numbers?", http://www.youtube.com/watch?v=QdHfIRaxbsI Там вопрос про достоверность информации в Вики очень даже неплохо освещён.
3. Так это ж я ещё про C# не написал! Но терпение, ждите на ваших экранах!
4. Слов _НЕОБХОДИМО_ и _КАК_ в русском языке нет, потому не понимаю, о чём ты.
О, кажется дошло! А сейчас будет подкол:
featZima:
On 12.09.2011 11:55, Дмитрий Глинский wrote:
Итак) Первое, что ждут от любого нормального языка, соотвествие своим ожиданим, что за хрень, почему при сравнении двух одинаковых строк получаем false ???
p.s. сейчас прийдётся открывать гугл и тратить безценное время на такую мелочь...
Shalfey:
Абсолютно правильное замечание.
String s = "...";
String t = "...";
// comparison of two strings
if(s.equals(t)){
System.out.println("Strings are the same!");
}
// Why we can't use operation ==
Operation == defines, if the strings are located in the same area in memory. We can't use it for comparison because of special behaviour of different virtual machines.If the virtual machine always provides collaborative use and location of the same strings, we can use the operation == to compare them. But only constant strings can be used and stored in such way. We can't use this operation with strings, that were get as results of operations + or substring for example.
That's why it's always better to use the equals method.
You can also use the analogue of the strcmp function from the C programming language. In Java it's named compareTo.
if(greeting.compareTo("Help") == 0){
System.out.println("Strings are the same!");
}
Shalfey to featZima:
Джава - 2 класса в 1 файле - ты говорил, что это невозможно. Вот тебе пример, умник:
import javax.swing.*;
// main class
public class sample {
public static void main(String[] args){
Frame frm = new Frame();
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setVisible(true);
}
}
// additional class
class Frame extends JFrame{
private static final int DEFAULT_HEIGHT = 100;
private static final int DEFAULT_WIDTH = 200;
public Frame(){
setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
}
// As you can see, we've got two different classes in one file.
// Any questions?
Резюме: чья бы корова мычала. Конечно, проще педалить почти ничего не зная и говорить, что язык - говно, нежели почитать документацию.
Стильно, модно, молодёжно!
Ну ты загнул) Одно дело системная функция, класс, или что-нибудь подобное :: тут всегда нужна документация, но! когда управляемый язык переопределяет оператор сравнения строк в оператор сравнения указателей -- извольте, мне этого не понять)
УдалитьДима, хватит строить из себя умного программиста! Кого ты обманываешь?
УдалитьУмный программист посмотрит в правильные книги/документы и прочтёт, что для любого ссылочного типа операция "==" определена в C# именно как сравнение адресов объектов. ЕДИНСТВЕННОЕ ИСКЛЮЧЕНИЕ сделано для строк - там операция "==" сравнивает значения объектов, а не их адреса. Т.е. сравнение строк с помощью вышеприведенной операции является ИСКЛЮЧЕНИЕМ ИЗ ПРАВИЛА.
В это же время в Java такого исключения нет. Значится, более предсказуемый и продуманный подход.
Если что - обращайся к господину Троелсену за подробностями.
Опять же: строки -- это элементарный тип в понимании любого начинающего программиста) И хоть во многих языках есть классы для их отображения, сравниваться они должны как элементарные типы!
УдалитьПро строки - элементарный тип - С-шникам расскажи, они посмеются. Про ассемблерщиков не вспоминаю.
УдалитьСтроки никому ничего не должны. Тем более тебе.
Ну-ну, Дмитрий. Я бы не был так категоричен на Вашем месте. Не всем с полпинка понятен чистый C, а уж логику в нем искать способны лишь знатоки.
ОтветитьУдалитьОтносительно примера: в первом блоке инициализация указателя (!) с помощью векторной формы оператора new синтаксически допустима, НО! Ты получаешь указатель на память в куче, да, но Страуструп тебя упаси что-либо туда записать — heap corruption гарантировано. Думаю, это связано с администратором кучи каким-то особым образом; во втором блоке сигнатура strncpy действительно возлагает на программиста большую ответственность за конец строки; и в третьем блоке все выглядит корректно. Обычно для простоты делают так: выделяют буфер под строку нужной длинны + 1 для нуль-терминатора, потом забивают его нулями (memset), а уж потом копируют туда данные (последний символ таким образом не нуждается в установке в ноль).
Пока WinAPI или интерфейс других ОС используют С-строки, у нас — системных программистов нет иного выбора, кроме как разбираться в этих вопросах. Я лично по максимуму заворачиваю все в std::string, но там, где такой возможности нет — использую массивы символов и безопасные функции по работе с ними.
Всё по делу, читать приятно!
Удалить>>> Ты получаешь указатель на память в куче, да, но Страуструп тебя упаси что-либо туда записать — heap corruption гарантировано.
УдалитьЯ же говорю, всё от незнания происходит =) Читаем выше и понимает, что класть можно и вполне, вполне безопасно)
>> у нас — системных программистов ...
ОтветитьУдалитьвыход есть! он прямо за решёткой --->>>> C#
По делу уже нечего сказать?
УдалитьТа надоело Вас уже учить праведному делу)
Удалить"Я гуру, я учітєль! Несіть мені усі по три рубля! І мудрості я дам вам ..."
Удалить#include "iostream"
Удалитьint main(void)
{
char* myString = new char[0];
myString[0] = 'H';
myString[1] = 'i';
myString[2] = '!';
myString[3] = 0;
std::cout << myString << std::endl;
return 0;
}
Такое чудо природы будет работать и работать будет потому, что все 32-битные компиляторы реально резервируют как минимум 4 байта под локальные переменные любых видов, т.к. это необходимо для выравнивания стека (и дизассемблерные листинги наглядно подтверждают это!).
Так-с, коллеги, я в замешательстве. Во-первых: я был неправ, когда говорил, что к памяти выделенной векторным new для указателя на char нельзя достучаться для записи без heap corruption — можно, как в примере Дмитрия. Во-вторых: на самом деле доступно далеко не 4 байта и выравнивание тут не при чем — включал/отключал. Эмпирически я установил границу, до которой не возникает повреждения кучи - 24 байта и это мне совсем непонятно.
УдалитьИ еще: любая форма delete (как векторная так и скалярная) вызванная для нашего указателя вызывает heap corruption, что ввело меня в заблуждение изначально.
Ах этот дивный язык! Сколько ещё в нём скрыто загадок!
УдалитьРябата!!! Какие загадки, на все есть исходники компилятора) Опять же, поведение абсолютно правильно и логично, вопрос только один "Зачем?", если есть C# 0=)
Удалить/* Malloc implementation for multiple threads without lock contention.
Copyright (C) 1996-2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Wolfram Gloger
and Doug Lea , 2001.
...
* Vital statistics:
Supported pointer representation: 4 or 8 bytes
Supported size_t representation: 4 or 8 bytes
Note that size_t is allowed to be 4 bytes even if pointers are 8.
You can adjust this by defining INTERNAL_SIZE_T
Alignment: 2 * sizeof(size_t) (default)
(i.e., 8 byte alignment with 4byte size_t). This suffices for
nearly all current machines and C compilers. However, you can
define MALLOC_ALIGNMENT to be wider than this if necessary.
Minimum overhead per allocated chunk: 4 or 8 bytes
Each malloced chunk has a hidden word of overhead holding size
and status information.
Minimum allocated size: 4-byte ptrs: 16 bytes (including 4 overhead)
8-byte ptrs: 24/32 bytes (including, 4/8 overhead)
When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
needed; 4 (8) for a trailing size field and 8 (16) bytes for
free list pointers. Thus, the minimum allocatable size is
16/24/32 bytes.
Even a request for zero bytes (i.e., malloc(0)) returns a
pointer to something of the minimum allocatable size.
The maximum overhead wastage (i.e., number of extra bytes
allocated than were requested in malloc) is less than or equal
to the minimum size, except for requests >= mmap_threshold that
are serviced via mmap(), where the worst case wastage is 2 *
sizeof(size_t) bytes plus the remainder from a system page (the
minimal mmap unit); typically 4096 or 8192 bytes.
Да какие там исходники компилятора! При чём тут GNU C library, если мы использовали MS Visual Studio 2010.
УдалитьПри том, что исходников Visual Studio у нас нет, а посмотреть логику хочется) В любом случае как я предположил выше, для всех 32-битных компиляторов выделяется 4 байта, остальное зависит уже от конкретной реализации, которую я собственно и привёл)
Удалитьp.s. всё логично и правильно, спорить больше не о чем)
Я угораю ;-)
УдалитьКакие 32-битные компиляторы? Ты сам читал, что выложил?
Ото лишь бы что-то ляпнуть.
че тут? читать надо?
ОтветитьУдалитьДима? Залогинься!
УдалитьКонечно читай, правда толку от этого никакого.
УдалитьС первых строк можно было почувствовать, что статья написана холивара ради)
УдалитьНеужели? Ну-ка подробней, где там тема holly war, поднятая именно в ПОСТЕ?
УдалитьОлоло, пишите на Objective-C xD
ОтветитьУдалитьА по теме вспомнилась вот эта статья http://habrahabr.ru/post/137411/ про printf()
Есть идея создать сервис Грабли.com на котором люди будут делиться граблями, на которые они наступают.
Слон, инкубатор, половина.
Статья -- хорошая !..
УдалитьObjective-C -- плохой (..
Каждый кулик своё болото хвалит. Чем лучше-то ваша поделка?!
ОтветитьУдалитьПлатят больше) http://dou.ua/lenta/articles/developers-salaries-december-2011/
ОтветитьУдалитьПлатят хоть и больше, геммороя тоже больше.
УдалитьДа и вообще по-моему хорошим инженерам на любой технологии хорошо платят. Если конечно умеешь себя выгодно продать.
"Если конечно умеешь себя выгодно продать." — Что это значит в твоем понимании? Ты так часто повторяешь эту фразу, что просто нельзя не спросить, какой смысл ты в нее вкладываешь. Хорошим инженерам плохо платят на заводе, а инженеров в IT не так уж много - ремесленники в основном.
Удалитьпривет
ОтветитьУдалить