Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > VLA question

Reply
Thread Tools

VLA question

 
 
Keith Thompson
Guest
Posts: n/a
 
      06-27-2013
James Kuyper <(E-Mail Removed)> writes:
> On 06/27/2013 01:44 PM, Keith Thompson wrote:
>> Stephen Sprunk <(E-Mail Removed)> writes:
>>> On 27-Jun-13 07:28, James Kuyper wrote:

>> [...]
>>>> The value of a character literal will be same, whether it has type
>>>> 'int' or type 'char', so long as char is signed, or is unsigned with
>>>> CHAR_MAX <= INT_MAX. Only if CHAR_MAX > INT_MAX could it matter.
>>>> Character literals that currently have a negative value would instead
>>>> have a positive value greater than INT_MAX.
>>>
>>> The only example I can envision a problem with is a character literal
>>> that today is negative. IIRC, the conversion to char is well-defined in
>>> that case. However, if character literals were char, it'd have a large
>>> positive value. Storing in a char would still be fine, but storing in
>>> an int would require a possibly-problematic conversion.

>>
>> That doesn't seem right. A character constant that has a negative value
>> today (because plain char is a signed type) would still have a negative
>> value if character constants were of type char. It would just be a
>> negative value of type char.
>>
>> Here's a demonstration:
>>
>> #include <stdio.h>
>> int main(void) {
>> printf("'\\x80' = %d\n", '\x80');
>> return 0;
>> }
>>
>> On a system with CHAR_BIT==8, with plain char being signed, I get:
>>
>> '\x80' = -128
>>
>> If '\x80' were of type char, its value would be (char)-128, which would
>> be promoted to int (because printf is variadic), giving the same result.

>
> As I indicated above, the problem I described arises only on
> implementations where CHAR_MAX > INT_MAX. If CHAR_BIT==8, then you can't
> have been testing on such a system.


Sure I was using a system with CHAR_BIT==8.

My point was that I think Stephen is mistaken in his statement that:

The only example I can envision a problem with is a character
literal that today is negative. IIRC, the conversion to char is
well-defined in that case. However, if character literals were
char, it'd have a large positive value.

I don't think that changing charctaer constants from int to char
would cause the values of any such constants to change from negative
to positive, assuming the signedness of char isn't changed at the
same time.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      06-27-2013
Keith Thompson <(E-Mail Removed)> writes:

> James Kuyper <(E-Mail Removed)> writes:
>> On 06/27/2013 02:41 PM, Seebs wrote:
>>> On 2013-06-27, James Kuyper <(E-Mail Removed)> wrote:
>>>> As I indicated above, the problem I described arises only on
>>>> implementations where CHAR_MAX > INT_MAX. If CHAR_BIT==8, then you can't
>>>> have been testing on such a system.
>>>
>>> I was about to say "hang on, how can that happen, int must be at least
>>> as wide as char", but of course, it can happen if CHAR_MAX == UCHAR_MAX.

>>
>> Right - as I mentioned earlier, CHAR_MAX > INT_MAX implies that CHAR_MIN
>> == 0.

>
> Suppose CHAR_BIT==32, CHAR_MIN==-2**31, CHAR_MAX==2**31-1,
> sizeof(int)==1, and int has one padding bit, so INT_MAX==2**30-1.


"The precision of an integer type is the number of bits it uses to
represent values, excluding any sign and padding bits."

In your example, the padding bit means that the precision of int is less
than that of signed char. But that's not allowed because

"[t]he rank of a signed integer type shall be greater than the rank of
any signed integer type with less precision"

and

"[t]he rank of long long int shall be greater than the rank of long
int, which shall be greater than the rank of int, which shall be
greater than the rank of short int, which shall be greater than the
rank of signed char".

--
Ben.
 
Reply With Quote
 
 
 
 
Öö Tiib
Guest
Posts: n/a
 
      06-28-2013
On Thursday, 27 June 2013 18:41:08 UTC+3, Ike Naar wrote:
> On 2013-06-27, ?? Tiib <(E-Mail Removed)> wrote:
> > On Thursday, 27 June 2013 07:58:34 UTC+3, Ike Naar wrote:
> >> On 2013-06-26, ?? Tiib <(E-Mail Removed)> wrote:
> >> > Unless I misunderstand we are talking only of few idiomatic cases like
> >> > 'malloc(sizeof(T))'. A custom preprocessor that adds redundant casts
> >> > feels trivial to write.
> >>
> >> C++ has 'new T' which seems to be more idiomatic than 'malloc(sizeof(T)'.

> >
> > Indeed it is in C++ but not in C and we are discussing common subset.

>
> Others have stated that C++ and C are different languages and I agree
> with that. Though code written in the common subset is, technically,
> C++, it is often non-idiomatic C++.
> Many C-isms are considered bad style in C++.


Do not dump that common subset just because it is not idiomatic C++. I
agree with you about different languages and idioms, but that does not
matter when there is a situation that can be solved by using common subset.

Example good property of common subset between C and C++: It is better and
more modern C than C89. (by my taste and some others, YMMV)

Example situation where that property helps: Code is required to be C and
one of (multiple) targets is required to be Microsoft compiler. Microsoft
C compiler is basically C89 but Microsoft C++ compiler compiles
"common subset" pretty well (few warnings to silence).

See? The code is going to be far from idiomatic C++, but that does not
matter, it will be regardless compiled on C++ compiler.
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      06-28-2013
On Thursday, 27 June 2013 17:17:28 UTC+3, Eric Sosman wrote:
> On 6/26/2013 6:17 PM, Öö Tiib wrote:
> >[...]
> > Unless I misunderstand we are talking only of few idiomatic cases like
> > 'malloc(sizeof(T))'. A custom preprocessor that adds redundant casts
> > feels trivial to write.

>
> What's the correct cast to insert in
>
> ptr->link = malloc(sizeof *ptr->link);


If we are are preprocessing for C++11 compiler then something like:

ptr->link = (decltype(ptr->link))malloc(sizeof *ptr->link);

If for C++03 or earlier then its *lot* harder. Extensions may help.
For example g++ had 'typeof' extension that worked like 'decltype'.

> Here's another:
>
> #include <limits.h>
> #if INT_MAX >= 1000000
> int *array;
> #else
> long *array;
> #endif
> ...
>
> array = malloc(n * sizeof *array);


It is basically same.

array = (decltype(array))malloc(n * sizeof *array);

I pretty much see that this cast is redundant and
annoying from code's readability perspective.

> Note that simply running the source through a C preprocessor and
> then through the cast-adding tool produces a result that is not
> portable. A portable rewrite of the final line would be
>
> array =
> #if INT_MAX >= 1000000
> (int*)
> #else
> (long*)
> #endif
> malloc(n * sizeof *array);


Yes, Stroustrup proposed 'decltype' at 2002 but simple things like it
take decades like always. Recent versions of gcc, msvc, clang, icc
and even Borland's c++ builder seem to recognize decltype so it is
quite widely supported.

> "Trivial" is relative, but this doesn't feel "trivial" to me.


There may be other, even trickier cases. When a tool fails to
understand a piece of code then that indicates that human might
fail as well. So it may be better to simplify code not smartify tools.
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      06-28-2013
On 06/27/2013 06:28 PM, Keith Thompson wrote:
> James Kuyper <(E-Mail Removed)> writes:

....
>> As I indicated above, the problem I described arises only on
>> implementations where CHAR_MAX > INT_MAX. If CHAR_BIT==8, then you can't
>> have been testing on such a system.

>
> Sure I was using a system with CHAR_BIT==8.
>
> My point was that I think Stephen is mistaken in his statement that:
>
> The only example I can envision a problem with is a character
> literal that today is negative. IIRC, the conversion to char is
> well-defined in that case. However, if character literals were
> char, it'd have a large positive value.


He was just paraphrasing what I said - if he was wrong, I was wrong.

> I don't think that changing charctaer constants from int to char
> would cause the values of any such constants to change from negative
> to positive, assuming the signedness of char isn't changed at the
> same time.


6.4.4.4p10: "If an integer character constant contains a single
character or escape sequence, its value is the one that results when an
object with type char whose value is that of the single character or
escape sequence is converted to type int."
If a char object contains the representation of a value greater than
INT_MAX, when that value is converted to int, the result will be
negative. Therefore, under the current rules, the corresponding
character literals must have a negative value. If the rules were changed
to give them the type char, they would have the actual value of the
corresponding char objects, which would be greater than INT_MAX.
--
James Kuyper
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      06-28-2013
On 6/27/2013 10:03 PM, Öö Tiib wrote:
> On Thursday, 27 June 2013 17:17:28 UTC+3, Eric Sosman wrote:
>> On 6/26/2013 6:17 PM, Öö Tiib wrote:
>>> [...]
>>> Unless I misunderstand we are talking only of few idiomatic cases like
>>> 'malloc(sizeof(T))'. A custom preprocessor that adds redundant casts
>>> feels trivial to write.

>>
>> What's the correct cast to insert in
>>
>> ptr->link = malloc(sizeof *ptr->link);

>
> If we are are preprocessing for C++11 compiler then something like:
>
> ptr->link = (decltype(ptr->link))malloc(sizeof *ptr->link);
> [...]


Perhaps I've misunderstood (not for the first time, nor the
last): I thought the cast-adder would produce code that was valid
in the much-discussed "common subset" of C++ and C. Indeed, the
word "redundant" suggests that line, since only in C would the
cast be unnecessary. But then, the solution you offer is quite
clearly not part of any "common subset" ... So I'm afraid I just
haven't grasped your meaning.

--
Eric Sosman
(E-Mail Removed)d
 
Reply With Quote
 
Ian Collins
Guest
Posts: n/a
 
      06-28-2013
Eric Sosman wrote:
> On 6/27/2013 10:03 PM, Öö Tiib wrote:
>> On Thursday, 27 June 2013 17:17:28 UTC+3, Eric Sosman wrote:
>>> On 6/26/2013 6:17 PM, Öö Tiib wrote:
>>>> [...]
>>>> Unless I misunderstand we are talking only of few idiomatic cases like
>>>> 'malloc(sizeof(T))'. A custom preprocessor that adds redundant casts
>>>> feels trivial to write.
>>>
>>> What's the correct cast to insert in
>>>
>>> ptr->link = malloc(sizeof *ptr->link);

>>
>> If we are are preprocessing for C++11 compiler then something like:
>>
>> ptr->link = (decltype(ptr->link))malloc(sizeof *ptr->link);
>> [...]

>
> Perhaps I've misunderstood (not for the first time, nor the
> last): I thought the cast-adder would produce code that was valid
> in the much-discussed "common subset" of C++ and C. Indeed, the
> word "redundant" suggests that line, since only in C would the
> cast be unnecessary. But then, the solution you offer is quite
> clearly not part of any "common subset" ... So I'm afraid I just
> haven't grasped your meaning.


#if !defined __cplusplus
# define decltype(X) void*
#endif

?

--
Ian Collins
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      06-28-2013
On 6/28/2013 4:46 AM, Ian Collins wrote:
> Eric Sosman wrote:
>> On 6/27/2013 10:03 PM, Öö Tiib wrote:
>>> On Thursday, 27 June 2013 17:17:28 UTC+3, Eric Sosman wrote:
>>>> On 6/26/2013 6:17 PM, Öö Tiib wrote:
>>>>> [...]
>>>>> Unless I misunderstand we are talking only of few idiomatic cases like
>>>>> 'malloc(sizeof(T))'. A custom preprocessor that adds redundant casts
>>>>> feels trivial to write.
>>>>
>>>> What's the correct cast to insert in
>>>>
>>>> ptr->link = malloc(sizeof *ptr->link);
>>>
>>> If we are are preprocessing for C++11 compiler then something like:
>>>
>>> ptr->link = (decltype(ptr->link))malloc(sizeof *ptr->link);
>>> [...]

>>
>> Perhaps I've misunderstood (not for the first time, nor the
>> last): I thought the cast-adder would produce code that was valid
>> in the much-discussed "common subset" of C++ and C. Indeed, the
>> word "redundant" suggests that line, since only in C would the
>> cast be unnecessary. But then, the solution you offer is quite
>> clearly not part of any "common subset" ... So I'm afraid I just
>> haven't grasped your meaning.

>
> #if !defined __cplusplus
> # define decltype(X) void*
> #endif
>
> ?


Well, maybe. Sort of makes a mockery of the "common subset"
notion, though. Take it a step further:

#ifdef __cplusplus
// Arbitrary C++ code here
#else
// Arbitrary C code here
#end

.... and now the "common subset" includes the entirety of both
languages -- the subset is the union!

(Long ago in this newsgroup -- I think ANSI C was still
a draft, with `noalias' -- somebody posted a "Hello, World!"
program. The unusual feature was that the program would
output "Hello, World!" when its source was fed to a C
implementation *or* to a Fortran implementation *or* to the
Unix shell. So: Is it useful to speak of the "common subset"
of C, Fortran, and sh?)

--
Eric Sosman
(E-Mail Removed)d
 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      06-28-2013
On Friday, 28 June 2013 07:14:20 UTC+3, Eric Sosman wrote:
> On 6/27/2013 10:03 PM, Öö Tiib wrote:
> > On Thursday, 27 June 2013 17:17:28 UTC+3, Eric Sosman wrote:
> >> On 6/26/2013 6:17 PM, Öö Tiib wrote:
> >>> [...]
> >>> Unless I misunderstand we are talking only of few idiomatic cases like
> >>> 'malloc(sizeof(T))'. A custom preprocessor that adds redundant casts
> >>> feels trivial to write.
> >>
> >> What's the correct cast to insert in
> >>
> >> ptr->link = malloc(sizeof *ptr->link);

> >
> > If we are are preprocessing for C++11 compiler then something like:
> >
> > ptr->link = (decltype(ptr->link))malloc(sizeof *ptr->link);
> > [...]

>
> Perhaps I've misunderstood (not for the first time, nor the
> last): I thought the cast-adder would produce code that was valid
> in the much-discussed "common subset" of C++ and C.


It can be. Conditional compiling and macros have to be used for to get
rid of necessary for C++ and illegal in C things like 'extern "C"' or
'decltype' casts. I had something like that in mind:

ptr->link =
#if defined __cplusplus
(decltype(ptr->link))
#endif
malloc(sizeof *ptr->link);

However now I see that Ian Collins suggested even better way.

> Indeed, the word "redundant" suggests that line, since only in C would
> the cast be unnecessary. But then, the solution you offer is quite
> clearly not part of any "common subset" ... So I'm afraid I just
> haven't grasped your meaning.


"Redundant" because such casts lower readability of code (YMMV). When
something is needed that hurt readability then there are alternatives to
add them manually or to use a tool that adds them temporarily compiling
time. I often prefer latter.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      06-28-2013
David Brown <(E-Mail Removed)> writes:
[...]
> I agree with this. Almost all the code I write is in the common subset
> of C99 and C++. Certainly there is almost nothing that you can write
> that is valid and well-written C99 that does not have identical
> functionality in C++. The only feature of C99 that is arguably useful
> (in my code) but invalid in C++ is designated integers.


Do you mean designated initializers?

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Routing Between Two VLA Ns Bob Simon Cisco 5 02-06-2007 01:15 AM
VLA Question pemo C Programming 8 02-24-2006 01:04 PM
support of C99 VLA in compilers Ben Hinkle C Programming 6 12-15-2005 02:08 PM
Compound literals and VLA's William Ahern C Programming 6 08-24-2005 05:40 AM
[C99] local VLA with dimension given by a global var? MackS C Programming 15 02-21-2005 07:59 PM



Advertisments