Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

An interview question

19 views
Skip to first unread message

Debanjan

unread,
Mar 5, 2010, 3:08:06 PM3/5/10
to
Does there exist any other alternative data structure instead of
struct tm (having same memory allocated as this structure) ? So that I
could use strftime without declaring <time.h>

I am aware of the fact that relying on implicit declaration is not
good,but I faced this question in an interview.

To be precise I was asked to print the month for a corresponding
integer using standard library function,but not allowed to include any
header file.

He want me to solve the problem using standard library function,but
without declaring any header file and of-course I was not allowed to
copy paste either from <time.h>.What I was told that if I want to use
struct tm it's the same layout as http://en.wikipedia.org/wiki/Time.h,that
is the fifth member is the tm_mon.

Ian Collins

unread,
Mar 5, 2010, 3:21:20 PM3/5/10
to
Debanjan wrote:
> Does there exist any other alternative data structure instead of
> struct tm (having same memory allocated as this structure) ? So that I
> could use strftime without declaring <time.h>
>
> I am aware of the fact that relying on implicit declaration is not
> good,but I faced this question in an interview.
>
> To be precise I was asked to print the month for a corresponding
> integer using standard library function,but not allowed to include any
> header file.

That's about as bad as being asked to complete a driving test without
using a car.

You can't safely use any standard library functions without including
the headers that declare them and their data structures.

--
Ian Collins

Seebs

unread,
Mar 5, 2010, 3:28:18 PM3/5/10
to
On 2010-03-05, Debanjan <debanj...@gmail.com> wrote:
> He want me to solve the problem using standard library function,but
> without declaring any header file and of-course I was not allowed to
> copy paste either from <time.h>.What I was told that if I want to use
> struct tm it's the same layout as http://en.wikipedia.org/wiki/Time.h,that
> is the fifth member is the tm_mon.

Sounds stupid to me. I would see no reason to attempt such a thing, I
also don't necessarily think it's a good thing to make the assumption that
struct tm has exactly those members in that order. It may or may not be
guaranteed, I can't remember, but... I sure wouldn't wanna bet on it.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

Debanjan

unread,
Mar 5, 2010, 3:43:44 PM3/5/10
to
> Sounds stupid to me.  I would see no reason to attempt such a thing, I
> also don't necessarily think it's a good thing to make the assumption that
> struct tm has exactly those members in that order.  It may or may not be
> guaranteed, I can't remember, but... I sure wouldn't wanna bet on it.

May be he wants some platform specific stuffs !

Seebs

unread,
Mar 5, 2010, 3:46:50 PM3/5/10
to
On 2010-03-05, Debanjan <debanj...@gmail.com> wrote:

Sounds like a pretty bad interview question to me.

Look at it this way: It doesn't sound like a question I'd be able to answer.
I was on the language committee for about a decade, and I've done compiler
maintenance. If a question on an interview sounds to me like it's
unanswerable, I respectfully submit that the question is probably poorly
chosen. :)

Andrew Poelstra

unread,
Mar 5, 2010, 3:47:45 PM3/5/10
to
On 2010-03-05, Debanjan <debanj...@gmail.com> wrote:

Maybe he's an imbecile. You don't want to work for him.

--
Andrew Poelstra
http://www.wpsoftware.net/andrew

Ben Pfaff

unread,
Mar 5, 2010, 3:51:05 PM3/5/10
to
Ian Collins <ian-...@hotmail.com> writes:

> You can't safely use any standard library functions without including
> the headers that declare them and their data structures.

I don't recommend doing it, but some standard library functions
may legitimately be used without including the appropriate
standard header:

7.1.4 Use of library functions
...
2 Provided that a library function can be declared without
reference to any type defined in a header, it is also
permissible to declare the function and use it without
including its associated header.
--
"...what folly I commit, I dedicate to you."
--William Shakespeare, _Troilus and Cressida_

Keith Thompson

unread,
Mar 5, 2010, 4:11:10 PM3/5/10
to
Debanjan <debanj...@gmail.com> writes:
> Does there exist any other alternative data structure instead of
> struct tm (having same memory allocated as this structure) ? So that I
> could use strftime without declaring <time.h>
>
> I am aware of the fact that relying on implicit declaration is not
> good,but I faced this question in an interview.

Sounds like a silly question. "Write some bad code to perform this
task."

I would have stated very clearly that using strftime without
"#include <time.h>" is very poor practice, and not something I'd be
willing to do in real life. (It's not inconceivable that that's
the response they were looking for.) Then, if they acknowledged
the point and said they still wanted me to do it, I'd go ahead and
give it my best shot.

> To be precise I was asked to print the month for a corresponding
> integer using standard library function,but not allowed to include any
> header file.
>
> He want me to solve the problem using standard library function,but
> without declaring any header file and of-course I was not allowed to
> copy paste either from <time.h>.What I was told that if I want to use
> struct tm it's the same layout as http://en.wikipedia.org/wiki/Time.h,that
> is the fifth member is the tm_mon.

If you were told to assume a certain layout, then you can legitimately
do so for the purpose of solving the immediate problem. But the standard
says:

The tm structure shall contain at least the following members,
in any order.

You cannot write portable code that uses struct tm without obtaining
the implementation's declaration for the type, preferably via
"#include <time.h>", or possibly by effectively copy-and-pasting the
declaration from <time.h>.

Well, I suppose you could write some test code that examines the
result of strftime() for various assumed layouts. I don't think
there's any way to guarantee that you'll actually find the correct
layout that way, but you probably will if the implementation hasn't
gone out of its way to prevent it (say, by starting the struct
with a kilobyte of padding). But it doesn't sound like that's what
they were looking for.

For that matter, I suspect that most or all implementations declare
the members in the order shown in the standard; there's just no
good reason not to.

Again, it's a silly question, though I suppose a demonstrated ability
to solve it and/or to explain why a *good* solution is impossible
could tell them something about your knowledge of C.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Eric Sosman

unread,
Mar 5, 2010, 4:24:53 PM3/5/10
to
On 3/5/2010 3:08 PM, Debanjan wrote:
> Does there exist any other alternative data structure instead of
> struct tm (having same memory allocated as this structure) ? So that I
> could use strftime without declaring<time.h>

No reliable way. The Standard specifies the names and
types of various elements of a struct tm, but does not specify
their arrangement. Also, it permits the implementation to
include additional, unspecified fields in the struct. As far
as I can tell, you cannot even figure out how big a struct tm
is, never mind its internal arrangement and its alignment.

> To be precise I was asked to print the month for a corresponding
> integer using standard library function,but not allowed to include any
> header file.

Hold on: The "corresponding integer" is given? That is,
you've already got a number 0,1,...,11 and you need to print
the name of the month? If that's the task, why bother with
<time.h> at all?

--
Eric Sosman
eso...@ieee-dot-org.invalid

Keith Thompson

unread,
Mar 5, 2010, 4:26:00 PM3/5/10
to
Eric Sosman <eso...@ieee-dot-org.invalid> writes:
> On 3/5/2010 3:08 PM, Debanjan wrote:
>> Does there exist any other alternative data structure instead of
>> struct tm (having same memory allocated as this structure) ? So that I
>> could use strftime without declaring<time.h>
>
> No reliable way. The Standard specifies the names and
> types of various elements of a struct tm, but does not specify
> their arrangement. Also, it permits the implementation to
> include additional, unspecified fields in the struct. As far
> as I can tell, you cannot even figure out how big a struct tm
> is, never mind its internal arrangement and its alignment.
[...]

What's wrong with sizeof (struct tm)?

Ian Collins

unread,
Mar 5, 2010, 4:31:18 PM3/5/10
to
Ben Pfaff wrote:
> Ian Collins <ian-...@hotmail.com> writes:
>
>> You can't safely use any standard library functions without including
>> the headers that declare them and their data structures.
>
> I don't recommend doing it, but some standard library functions
> may legitimately be used without including the appropriate
> standard header:
>
> 7.1.4 Use of library functions
> ....

> 2 Provided that a library function can be declared without
> reference to any type defined in a header, it is also
> permissible to declare the function and use it without
> including its associated header.

That's why I added "and their data structures"!

In the OP's context, struct tm is a classic case of a structure defined
(by the standard) to include minimum set of members. An implementation
is free to add some of its own.

--
Ian Collins

Ian Collins

unread,
Mar 5, 2010, 4:33:34 PM3/5/10
to
Keith Thompson wrote:
> Eric Sosman <eso...@ieee-dot-org.invalid> writes:
>> On 3/5/2010 3:08 PM, Debanjan wrote:
>>> Does there exist any other alternative data structure instead of
>>> struct tm (having same memory allocated as this structure) ? So that I
>>> could use strftime without declaring<time.h>
>> No reliable way. The Standard specifies the names and
>> types of various elements of a struct tm, but does not specify
>> their arrangement. Also, it permits the implementation to
>> include additional, unspecified fields in the struct. As far
>> as I can tell, you cannot even figure out how big a struct tm
>> is, never mind its internal arrangement and its alignment.
> [...]
>
> What's wrong with sizeof (struct tm)?

You have to include <time.h>!

--
Ian Collins

Eric Sosman

unread,
Mar 5, 2010, 4:41:50 PM3/5/10
to
On 3/5/2010 4:26 PM, Keith Thompson wrote:
> Eric Sosman<eso...@ieee-dot-org.invalid> writes:
>> On 3/5/2010 3:08 PM, Debanjan wrote:
>>> Does there exist any other alternative data structure instead of
>>> struct tm (having same memory allocated as this structure) ? So that I
>>> could use strftime without declaring<time.h>
>>
>> No reliable way. The Standard specifies the names and
>> types of various elements of a struct tm, but does not specify
>> their arrangement. Also, it permits the implementation to
>> include additional, unspecified fields in the struct. As far
>> as I can tell, you cannot even figure out how big a struct tm
>> is, never mind its internal arrangement and its alignment.
> [...]
>
> What's wrong with sizeof (struct tm)?

Nothing -- except that he's operating under the silly
restriction of not including any Standard headers. So, where
does he get a struct tm declaration that's known to be the
same size as the implementation's own version?

Hmmm: It occurs to me that if he knew the size, or an
upper bound on the size, he could dodge the alignment issue
by obtaining the memory from malloc() (declared free-hand).
He still wouldn't know how to find the various elements within
the struct, though.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Keith Thompson

unread,
Mar 5, 2010, 4:39:10 PM3/5/10
to

Whoops, context error.

Ben Pfaff

unread,
Mar 5, 2010, 5:05:20 PM3/5/10
to
Ian Collins <ian-...@hotmail.com> writes:

> Ben Pfaff wrote:
>> Ian Collins <ian-...@hotmail.com> writes:
>>
>>> You can't safely use any standard library functions without including
>>> the headers that declare them and their data structures.
>>
>> I don't recommend doing it, but some standard library functions
>> may legitimately be used without including the appropriate
>> standard header:
>>
>> 7.1.4 Use of library functions
>> ....
>> 2 Provided that a library function can be declared without
>> reference to any type defined in a header, it is also
>> permissible to declare the function and use it without
>> including its associated header.
>
> That's why I added "and their data structures"!

I can use exit() by declaring it myself, without including
<stdlib.h>, but your statement (quoted above) says that I can't.
So your statement is wrong.
--
"IMO, Perl is an excellent language to break your teeth on"
--Micah Cowan

Default User

unread,
Mar 5, 2010, 5:30:35 PM3/5/10
to
Seebs wrote:

> Sounds like a pretty bad interview question to me.

Sounds like a terrific one to me. You can just get up, shake his hand,
and leave without wasting any more of your time.

Brian

--
Day 396 of the "no grouchy usenet posts" project

Seebs

unread,
Mar 5, 2010, 6:23:25 PM3/5/10
to
On 2010-03-05, Default User <defaul...@yahoo.com> wrote:
> Seebs wrote:
>> Sounds like a pretty bad interview question to me.

> Sounds like a terrific one to me. You can just get up, shake his hand,
> and leave without wasting any more of your time.

Oooh, good point. I had not considered that angle.

Keith Thompson

unread,
Mar 5, 2010, 8:23:09 PM3/5/10
to
"Default User" <defaul...@yahoo.com> writes:
> Seebs wrote:
>> Sounds like a pretty bad interview question to me.
>
> Sounds like a terrific one to me. You can just get up, shake his hand,
> and leave without wasting any more of your time.

Or you can tell the interviewer that it's a very silly thing to do,
and he can tell you that was the answer he was looking for.

Tim Rentsch

unread,
Mar 6, 2010, 9:48:37 AM3/6/10
to
Eric Sosman <eso...@ieee-dot-org.invalid> writes:

> On 3/5/2010 4:26 PM, Keith Thompson wrote:
>> Eric Sosman<eso...@ieee-dot-org.invalid> writes:
>>> On 3/5/2010 3:08 PM, Debanjan wrote:
>>>> Does there exist any other alternative data structure instead of
>>>> struct tm (having same memory allocated as this structure) ? So that I
>>>> could use strftime without declaring<time.h>
>>>
>>> No reliable way. The Standard specifies the names and
>>> types of various elements of a struct tm, but does not specify
>>> their arrangement. Also, it permits the implementation to
>>> include additional, unspecified fields in the struct. As far
>>> as I can tell, you cannot even figure out how big a struct tm
>>> is, never mind its internal arrangement and its alignment.
>> [...]
>>
>> What's wrong with sizeof (struct tm)?
>
> Nothing -- except that he's operating under the silly
> restriction of not including any Standard headers. So, where
> does he get a struct tm declaration that's known to be the
> same size as the implementation's own version?
>
> Hmmm: It occurs to me that if he knew the size, or an
> upper bound on the size, he could dodge the alignment issue
> by obtaining the memory from malloc() (declared free-hand).

> [snip]

If you use malloc this way, and without including any Standard
header, you run the risk of undefined behavior. Arguably the
risk of UB is 100%, but certainly it is non-zero.

Tim Rentsch

unread,
Mar 6, 2010, 9:54:37 AM3/6/10
to
Seebs <usenet...@seebs.net> writes:

> On 2010-03-05, Debanjan <debanj...@gmail.com> wrote:
>>> Sounds stupid to me. I would see no reason to attempt such a thing, I
>>> also don't necessarily think it's a good thing to make the assumption that
>>> struct tm has exactly those members in that order. It may or may not be
>>> guaranteed, I can't remember, but... I sure wouldn't wanna bet on it.
>
>> May be he wants some platform specific stuffs !
>
> Sounds like a pretty bad interview question to me.
>
> Look at it this way: It doesn't sound like a question I'd be able to answer.
> I was on the language committee for about a decade, and I've done compiler
> maintenance. If a question on an interview sounds to me like it's
> unanswerable, I respectfully submit that the question is probably poorly
> chosen. :)

You may be assuming the OP has relayed the question accurately;
he might not have. Also the interviewer may have had other,
quite different motivations for asking the question, which
didn't come through in the posted description.

Eric Sosman

unread,
Mar 6, 2010, 10:41:45 AM3/6/10
to

ITYM "< 100%", but I see what you're getting at: If size_t
is narrower than int, you can't call malloc() correctly without
a prototype in scope -- and you can't write the prototype
without a declaration of size_t, which you can only get from
a header.

Okay, back to the drawing board. (Besides, the whole dodge
was predicated on knowing an upper bound for sizeof(struct tm)
without actually knowing what a struct tm looks like -- which
is already something of a stretch.)

--
Eric Sosman
eso...@ieee-dot-org.invalid

Tim Rentsch

unread,
Mar 6, 2010, 10:54:46 AM3/6/10
to
Eric Sosman <eso...@ieee-dot-org.invalid> writes:

> On 3/6/2010 9:48 AM, Tim Rentsch wrote:
>> Eric Sosman<eso...@ieee-dot-org.invalid> writes:
>>>
>>> Hmmm: It occurs to me that if he knew the size, or an
>>> upper bound on the size, he could dodge the alignment issue
>>> by obtaining the memory from malloc() (declared free-hand).
>>> [snip]
>>
>> If you use malloc this way, and without including any Standard
>> header, you run the risk of undefined behavior. Arguably the
>> risk of UB is 100%, but certainly it is non-zero.
>
> ITYM "< 100%", but I see what you're getting at: If size_t
> is narrower than int, you can't call malloc() correctly without
> a prototype in scope -- and you can't write the prototype
> without a declaration of size_t, which you can only get from
> a header.

Actually I did mean (arguably) == 100% rather than < 100%, but you
got the main point I was making. (The question is whether 7.1.4p2
can be satisfied at all without reference to 'size_t'; if 7.1.4p2
can't be satisfied, I believe UB is guaranteed.)

santosh

unread,
Mar 6, 2010, 3:06:29 PM3/6/10
to
Debanjan <debanj...@gmail.com> writes:

Ok. Fine. Your interviewer has given you the layout for struct tm.
Just declare it yourself, and use strftime().

Wait, are you disallowed merely from using time.h, or from all
standard headers? If the latter, then you can't use strftime() since
you won't have the definition for size_t. One possibility is to
declare yourself asctime(), and use it. But it won't simply give you
just the representation for tm_mon.


Eric Sosman

unread,
Mar 6, 2010, 3:07:24 PM3/6/10
to

The implementation defines whether size_t promotes to int
or does not. If it doesn't promote, you can write a free-hand
prototypeless declaration of malloc() and you can call it with
a single size_t argument (derived from sizeof, since we don't
know how to declare size_t), and the behavior is well-defined.
If size_t promotes, it's impossible to call unprototyped malloc()
correctly, and the behavior is undefined.

So it's implementation-defined whether it's defined or
undefined. ;-)

--
Eric Sosman
eso...@ieee-dot-org.invalid

Richard Bos

unread,
Mar 6, 2010, 4:49:11 PM3/6/10
to
Debanjan <debanj...@gmail.com> wrote:

> I am aware of the fact that relying on implicit declaration is not
> good,but I faced this question in an interview.
>
> To be precise I was asked to print the month for a corresponding
> integer using standard library function,but not allowed to include any
> header file.

I'd have walked out at this point. I'd rather starve than go postal.

Richard

Eric Sosman

unread,
Mar 6, 2010, 5:38:35 PM3/6/10
to

Maybe the question was intended to explore the O.P.'s
attention to detail in a problem specification[*]. Here's my
suggested solution:

/* NOT RECOMMENDED! */
int puts(const char*);
void solution(int month) {
static const char *name[] = {
"January", "February", "March", "April", "May",
"June", "July", "August", "September", "October",
"November", "December", "Pretender"
}
if (month < 0 || month > 12)
month = 12;
puts (name[month]);
}

I believe this meets the requirements as stated. The entire
strftime() business seems to me to be a red herring.

[*] Long ago my high school math teacher gave just such
a test. At the end of some weeks' lessons about the geometry
of circles -- tangents, inscribed and circumscribed polygons,
perpendicularity of this and that, and so on -- he handed out
an in-class quiz. One big diagram at the top, showing a circle
plus assorted lines and points and angles, all with one-letter
labels, and ten true-or-false questions like "The line segments
AB and XY have the same length." The tenth question was "Point
C is the center of the circle." Of course, by the time you got
that far (having ignored the standing advice to read all the way
through a test before starting to answer), you'd already assumed
"C is the center"[**] in answering the first nine ...

[**] The return to topicality.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Keith Thompson

unread,
Mar 6, 2010, 9:56:00 PM3/6/10
to

I think that, if you happen to know that size_t is a typedef for, say,
unsigned long on a given implementation, you can safely declare

void *malloc(unsigned long size);

and call it with no risk of UB *for that implementation*. If size_t
is declared as

typedef unsigned long size_t;

then size_t isn't just another type that looks like unsigned long; it
*is* unsigned long (or rather, it's another name for unsigned long).

Of course it's silly and dangerous to do this rather than just
#including the proper header unless you're forced to work around a
broken implementation.

Moi

unread,
Mar 7, 2010, 6:25:03 AM3/7/10
to
On Sat, 06 Mar 2010 18:56:00 -0800, Keith Thompson wrote:

> Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> writes:
>> Eric Sosman <eso...@ieee-dot-org.invalid> writes:
>>> On 3/6/2010 9:48 AM, Tim Rentsch wrote:
>>>> Eric Sosman<eso...@ieee-dot-org.invalid> writes:
>
>
> I think that, if you happen to know that size_t is a typedef for, say,
> unsigned long on a given implementation, you can safely declare
>
> void *malloc(unsigned long size);
>
> and call it with no risk of UB *for that implementation*. If size_t is
> declared as
>
> typedef unsigned long size_t;
>

IMHO the sizeof operator evaluates to a size_t, or at least
to a unsigned type that is compatible with a size_t.

So basically you could use the "sizeof expression" syntax:

unsigned sizeofsizeof;

sizeofsizeof = sizeof sizeof 0+0;

AvK

Ben Bacarisse

unread,
Mar 7, 2010, 8:38:43 AM3/7/10
to
Moi <ro...@invalid.address.org> writes:

Did you mean that? It parses as (sizeof (sizeof 0)) + 0. What is the
0+0 for?

I can't see how knowing the size of a size_t helps here. Calling a
function with the wrong type of argument is UB even if the size of the
argument is correct. In practical terms, getting the size right (for
an integer argument) is often the thing that matters so I suppose that
might have been part of the intent of the question.

--
Ben.

Keith Thompson

unread,
Mar 7, 2010, 2:39:56 PM3/7/10
to
Moi <ro...@invalid.address.org> writes:
> On Sat, 06 Mar 2010 18:56:00 -0800, Keith Thompson wrote:
>
>> Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> writes:
>>> Eric Sosman <eso...@ieee-dot-org.invalid> writes:
>>>> On 3/6/2010 9:48 AM, Tim Rentsch wrote:
>>>>> Eric Sosman<eso...@ieee-dot-org.invalid> writes:
>>
>>
>> I think that, if you happen to know that size_t is a typedef for, say,
>> unsigned long on a given implementation, you can safely declare
>>
>> void *malloc(unsigned long size);
>>
>> and call it with no risk of UB *for that implementation*. If size_t is
>> declared as
>>
>> typedef unsigned long size_t;
>>
>
> IMHO the sizeof operator evaluates to a size_t, or at least
> to a unsigned type that is compatible with a size_t.

"IMHO"? This isn't a matter of opinion; the standard says that sizeof
yields a size_t result. C99 6.5.3.4p4:

The value of the result is implementation-defined, and its type
(an unsigned integer type) is size_t, defined in <stddef.h>
(and other headers).

> So basically you could use the "sizeof expression" syntax:
>
> unsigned sizeofsizeof;
>
> sizeofsizeof = sizeof sizeof 0+0;

Ben already covered this. "sizeof sizeof 0" is a simpler way to
get the size of size_t ("sizeof(size_t) is even simpler, but we're
assuming that we're not allowed to #include standard headers).
But knowing the size of size_t doesn't tell you its type.

Given the original (rather silly) problem statement, size_t isn't even
an issue. The standard's synopsis for strftime() is:

#include <time.h>
size_t strftime(char * restrict s,
size_t maxsize,
const char * restrict format,
const struct tm * restrict timeptr);

and the interviewer assumed that you could savely redeclare "struct
tm" by hand, without reference to the implementation's <time.h>.
Given this assumption, you could safely pass "sizeof s" as the second
argument, where s is the target array. Handling (even ignoring)
the result is still a problem, but I suspect that's just something
the interviewer hadn't thought of.

Or the interviewer is more clever than most of us have assumed,
and the point of the question was to elicit these objections.

Moi

unread,
Mar 7, 2010, 3:26:59 PM3/7/10
to
On Sun, 07 Mar 2010 13:38:43 +0000, Ben Bacarisse wrote:

> Moi <ro...@invalid.address.org> writes:
>
>> On Sat, 06 Mar 2010 18:56:00 -0800, Keith Thompson wrote:
>>
>>> Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> writes:
>>>> Eric Sosman <eso...@ieee-dot-org.invalid> writes:
>>>>> On 3/6/2010 9:48 AM, Tim Rentsch wrote:
>>>>>> Eric Sosman<eso...@ieee-dot-org.invalid> writes:
>>>
>>>

>>>
>> IMHO the sizeof operator evaluates to a size_t, or at least to a
>> unsigned type that is compatible with a size_t.
>>
>> So basically you could use the "sizeof expression" syntax:
>>
>> unsigned sizeofsizeof;
>>
>> sizeofsizeof = sizeof sizeof 0+0;
>
> Did you mean that? It parses as (sizeof (sizeof 0)) + 0. What is the
> 0+0 for?
>

To catch your attention. The essence is that sizeof yields a size_t
*even if size_t has not been typedeffed yet*


> I can't see how knowing the size of a size_t helps here. Calling a
> function with the wrong type of argument is UB even if the size of the
> argument is correct. In practical terms, getting the size right (for an
> integer argument) is often the thing that matters so I suppose that
> might have been part of the intent of the question.

Knowing the size could be useful to create fake function declarations for
malloc() or strlen().

unsigned long long mystrlen(const char *str)
{

if (sizeofsizeof == sizeof (unsigned long)) {
unsigned long long strlen(char const *str);
return strlen (str);
}
else if (sizeof sizeof == sizeof (unsigned long)) {

unsigned long strlen(char const *str);
return strlen(str);
}
else ...
}

This enables one to perform the call without size_t typedeffed.
(which of course is silly, just as the interview question
was silly in the first place)

Moi

unread,
Mar 7, 2010, 3:31:24 PM3/7/10
to

oops that should of course have been

if (sizeofsizeof == sizeof (unsigned long long)) {


> unsigned long long strlen(char const *str); return strlen (str);


AvK

Eric Sosman

unread,
Mar 7, 2010, 4:35:31 PM3/7/10
to
On 3/7/2010 3:26 PM, Moi wrote:
> On Sun, 07 Mar 2010 13:38:43 +0000, Ben Bacarisse wrote:
>
>> Moi<ro...@invalid.address.org> writes:
>>> [...]

>>> unsigned sizeofsizeof;
>>> sizeofsizeof = sizeof sizeof 0+0;
>>
>> Did you mean that? It parses as (sizeof (sizeof 0)) + 0. What is the
>> 0+0 for?
>
> To catch your attention. The essence is that sizeof yields a size_t
> *even if size_t has not been typedeffed yet*

Yes, of course. Everybody knows that. It doesn't help.

>> I can't see how knowing the size of a size_t helps here. Calling a
>> function with the wrong type of argument is UB even if the size of the
>> argument is correct. In practical terms, getting the size right (for an
>> integer argument) is often the thing that matters so I suppose that
>> might have been part of the intent of the question.
>
> Knowing the size could be useful to create fake function declarations for
> malloc() or strlen().

How? On every system I've used, size_t is the same size as
one or the other of float or double, but it doesn't follow that

void *malloc(float);
double strlen(const char*);

... could be correct declarations, or even close to correct. Size
is an attribute of (object) type, but size is not type.

> unsigned long long mystrlen(const char *str)
> {
>
> if (sizeofsizeof == sizeof (unsigned long)) {
> unsigned long long strlen(char const *str);
> return strlen (str);
> }
> else if (sizeof sizeof == sizeof (unsigned long)) {
>
> unsigned long strlen(char const *str);
> return strlen(str);
> }
> else ...
> }
>
> This enables one to perform the call without size_t typedeffed.

No, it does not. If size_t has the same size as unsigned int
(for example), it does not follow that size_t *is* unsigned int,
or is passed to and from functions the same way unsigned int is.
On all systems, char and unsigned char have the same size, and on
many systems both are unsigned. It does not follow that char *is*
unsigned char.

> (which of course is silly, just as the interview question
> was silly in the first place)

Time to drag this horse to the glue factory, I think.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Seebs

unread,
Mar 7, 2010, 5:08:32 PM3/7/10
to
On 2010-03-07, Eric Sosman <eso...@ieee-dot-org.invalid> wrote:
> ... could be correct declarations, or even close to correct. Size
> is an attribute of (object) type, but size is not type.

True.

You can come pretty close by observing that if you can find an unsigned
integer type t such that sizeof(t) == sizeof(sizeof(1)), it's probable
that t is the same type as size_t, but I think it's only probable, not
certain. The sizeof(float) question is less relevant; we are promised
that size_t is an unsigned integer type.

Eric Sosman

unread,
Mar 7, 2010, 5:38:00 PM3/7/10
to
On 3/7/2010 5:08 PM, Seebs wrote:
> On 2010-03-07, Eric Sosman<eso...@ieee-dot-org.invalid> wrote:
>> ... could be correct declarations, or even close to correct. Size
>> is an attribute of (object) type, but size is not type.
>
> True.
>
> You can come pretty close by observing that if you can find an unsigned
> integer type t such that sizeof(t) == sizeof(sizeof(1)), it's probable
> that t is the same type as size_t, but I think it's only probable, not
> certain. The sizeof(float) question is less relevant; we are promised
> that size_t is an unsigned integer type.

On my machine, sizeof(unsigned int) == sizeof(size_t) and
sizeof(unsigned long) == sizeof(size_t). Which of unsigned int
and unsigned long (if either) actually *is* size_t?

(It so happens that unsigned int and unsigned long and size_t
values are all passed to and from functions with identical code,
so -- on my machine -- the resulting undefined behavior would
turn out to be "what you wanted." Doesn't make it right, though.)

--
Eric Sosman
eso...@ieee-dot-org.invalid

Seebs

unread,
Mar 7, 2010, 9:56:32 PM3/7/10
to

My guess would be that, on 95% or more of systems (99.9% if we count
"number of machines you'll encounter", possibly lower if we count each
distinct system type only once), it would turn out that they would be
interchangeable -- in that it would never cause a problem to use one
where the other is expected, or specify the wrong one in a prototype.

Not saying it's not undefined behavior, but in practice I think it is
very likely to do what the user intends.

Eric Sosman

unread,
Mar 7, 2010, 10:17:00 PM3/7/10
to
On 3/7/2010 9:56 PM, Seebs wrote:
> [...]

> Not saying it's not undefined behavior, but in practice I think it is
> very likely to do what the user intends.

Yes. It's too bad, really. The user's intent is to be
purposefully perverse, and he shouldn't be rewarded for such
asininity aforethought. Let people get away with this kind
of bletcherous behavior, and the next thing you know they'll
be using tabs ...

--
Eric Sosman
eso...@ieee-dot-org.invalid

oksid

unread,
Mar 8, 2010, 3:53:46 AM3/8/10
to
Debanjan wrote:
> Does there exist any other alternative data structure instead of
> struct tm (having same memory allocated as this structure) ? So that I
> could use strftime without declaring<time.h>

Yes. gmtime() returns a pointer to a tm struct.

> He want me to solve the problem using standard library function,but
> without declaring any header file and of-course I was not allowed to
> copy paste either from<time.h>.What I was told that if I want to use
> struct tm it's the same layout as http://en.wikipedia.org/wiki/Time.h,that
> is the fifth member is the tm_mon.

Here is my solution:
---------------------------------------------------------
int main(int argc, char *argv[])
{
int month;

for (month = 0; month < 12; month++) {
unsigned int second;
char tmpbuf[128];
void *tm;
second = 60 * 60 * 24 * 31 * month;
tm = gmtime( &second );
strftime(tmpbuf, 128, "%B\r\n", tm );
printf(tmpbuf);
}
system("pause");
return 0;
}
---------------------------------------------------------
It works with Visual C++ .net (2002).

I don't need to know anything for struct tm because I'm referencing it
only though pointers.


--
Jean-Marc L.

Michael Foukarakis

unread,
Mar 8, 2010, 8:30:47 AM3/8/10
to
On Mar 5, 11:24 pm, Eric Sosman <esos...@ieee-dot-org.invalid> wrote:

> On 3/5/2010 3:08 PM, Debanjan wrote:
>
> > Does there exist any other alternative data structure instead of
> > struct tm (having same memory allocated as this structure) ? So that I
> > could use strftime without declaring<time.h>
>
>      No reliable way.  The Standard specifies the names and
> types of various elements of a struct tm, but does not specify
> their arrangement.  Also, it permits the implementation to
> include additional, unspecified fields in the struct.  As far
> as I can tell, you cannot even figure out how big a struct tm
> is, never mind its internal arrangement and its alignment.

I'm pretty sure this is the point of the question; to use strftime()
with the proper format specification (%b | %B) to print the month
instead of accessing struct tm directly, which you can't do without
including time.h. Of course, skipping header inclusions is still
stupid, but interview questions are designed to be stupid.

I assumed the "corresponding integer" you mention is the number of
seconds elapsed since the Epoch. If it's an ordinal, then it's trivial.

Ben Bacarisse

unread,
Mar 8, 2010, 11:30:45 AM3/8/10
to
oksid <ok...@bluewin.ch> writes:

> Debanjan wrote:
>> Does there exist any other alternative data structure instead of
>> struct tm (having same memory allocated as this structure) ? So that I
>> could use strftime without declaring<time.h>
>
> Yes. gmtime() returns a pointer to a tm struct.
>
>> He want me to solve the problem using standard library function,but
>> without declaring any header file and of-course I was not allowed to
>> copy paste either from<time.h>.What I was told that if I want to use
>> struct tm it's the same layout as http://en.wikipedia.org/wiki/Time.h,that
>> is the fifth member is the tm_mon.
>
> Here is my solution:
> ---------------------------------------------------------
> int main(int argc, char *argv[])
> {
> int month;
>
> for (month = 0; month < 12; month++) {
> unsigned int second;
> char tmpbuf[128];
> void *tm;
> second = 60 * 60 * 24 * 31 * month;
> tm = gmtime( &second );

What if time_t is not unsigned int? Also, gmtime is implicitly being
declared as int gmtime() here and the conversion of the result from int
to void * is unreliable. If you declared gmtime as returning a void *
you would still be calling a library function without a correct
declaration in scope and that is undefined behaviour.

> strftime(tmpbuf, 128, "%B\r\n", tm );
> printf(tmpbuf);
> }
> system("pause");
> return 0;
> }
> ---------------------------------------------------------
> It works with Visual C++ .net (2002).

That's one possible outcome where the standard does not define the
behaviour.

> I don't need to know anything for struct tm because I'm referencing it
> only though pointers.

Calling a library function without a correct declaration in scope
results in undefined behaviour. I agree that you are likely to find
implementations where this works, but you would have to fix the other
problems as well. For the record, on my system your code gives a
segmentation fault.

--
Ben.

Phred Phungus

unread,
Mar 9, 2010, 2:21:14 AM3/9/10
to
Keith Thompson wrote:

> Ben already covered this. "sizeof sizeof 0" is a simpler way to
> get the size of size_t ("sizeof(size_t) is even simpler, but we're
> assuming that we're not allowed to #include standard headers).
> But knowing the size of size_t doesn't tell you its type.

http://en.wikipedia.org/wiki/Size_t

That's a bit of a revelation for me, as I thought it was the biggest
integer an implementation could muster.

What did Eric mean with this:

> How? On every system I've used, size_t is the same size as
> one or the other of float or double, but it doesn't follow that

The width of the integer type that size_t is is either the width of the
implementation's float or double?
--
fred

Phred Phungus

unread,
Mar 9, 2010, 2:42:04 AM3/9/10
to
Keith Thompson wrote:
> Ian Collins <ian-...@hotmail.com> writes:

>> Keith Thompson wrote:
>>> Eric Sosman <eso...@ieee-dot-org.invalid> writes:
>>>> On 3/5/2010 3:08 PM, Debanjan wrote:
>>>>> Does there exist any other alternative data structure instead of
>>>>> struct tm (having same memory allocated as this structure) ? So that I
>>>>> could use strftime without declaring<time.h>
>>>> No reliable way. The Standard specifies the names and
>>>> types of various elements of a struct tm, but does not specify
>>>> their arrangement. Also, it permits the implementation to
>>>> include additional, unspecified fields in the struct. As far
>>>> as I can tell, you cannot even figure out how big a struct tm
>>>> is, never mind its internal arrangement and its alignment.
>>> [...]
>>>
>>> What's wrong with sizeof (struct tm)?
>> You have to include <time.h>!
>
> Whoops, context error.
>

Now that's funny. I see the context above, and, in that context I would
say the error were more just a plain old error.

Anyways, the absurdity of not having standard C headers to draw on
ignores C's place as the lingua franca. I read in the c.l.p.misc faq
that perl reads the C headers in /usr/include/ to "do" a syscall.

I think I can improve on that verb once I understand it myself.
--
fred

Richard Heathfield

unread,
Mar 9, 2010, 3:23:42 AM3/9/10
to

He meant that knowing the size of size_t doesn't tell you the type of
size_t.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within

Keith Thompson

unread,
Mar 9, 2010, 3:53:21 AM3/9/10
to
Phred Phungus <Ph...@example.invalid> writes:
> Keith Thompson wrote:
>> Ben already covered this. "sizeof sizeof 0" is a simpler way to
>> get the size of size_t ("sizeof(size_t) is even simpler, but we're
>> assuming that we're not allowed to #include standard headers).
>> But knowing the size of size_t doesn't tell you its type.
>
> http://en.wikipedia.org/wiki/Size_t
>
> That's a bit of a revelation for me, as I thought it was the biggest
> integer an implementation could muster.

No, it's merely the type returned by size_t, and by implication
an appropriate type for storing the size of an object in bytes.
On many systems, it's the same size as a pointer. You can very
easily have integer types bigger than any pointer type; systems
with 32-bit pointers, 32-bit size_t, and 64-bit long long
are common.

> What did Eric mean with this:
>
>> How? On every system I've used, size_t is the same size as
>> one or the other of float or double, but it doesn't follow that
>
> The width of the integer type that size_t is is either the width of
> the implementation's float or double?

The qualification "On every system I've used" is critical. On most
systems I've used, float is 32 bits, double is 64 bits, and size_t
is either 32 bits or 64 bits. There is no particular significance
to this (except perhaps that they're sizes that are likely to fit
in a CPU register). That was Eric's point. Two types that happen
to have the same size can nevertheless be distinct and incompatible
types.

Malcolm McLean

unread,
Mar 9, 2010, 4:24:35 AM3/9/10
to
On 9 Mar, 08:53, Keith Thompson <ks...@mib.org> wrote:

> Phred Phungus <Ph...@example.invalid> writes:
>
> > That's a bit of a revelation for me, as I thought it was the biggest
> > integer an implementation could muster.
>
> No, it's merely the type returned by size_t, and by implication
> an appropriate type for storing the size of an object in bytes.
> On many systems, it's the same size as a pointer.  You can very
> easily have integer types bigger than any pointer type; systems
> with 32-bit pointers, 32-bit size_t, and 64-bit long long
> are common.
>
Usually size_t will be the same size as a pointer and the same
registers will be used for both. That's because of the way most
processors work - integers are combined with addresses to produce
indexed addresses, and sent to retrive data from memory.
However you can have oddball architectures, the most significant of
which was the early x86 series, which had a segment-based addressing
system, so pointers were of the form segment:offset.

Michal Nazarewicz

unread,
Mar 9, 2010, 6:34:49 AM3/9/10
to
Debanjan <debanj...@gmail.com> writes:
> To be precise I was asked to print the month for a corresponding
> integer using standard library function, but not allowed to include
> any header file.

At this point I started wondering whether it is guaranteed that
functions like printf(), time(), etc. have external linkage. For
instance, can an implementation define printf() as:

#v+
static inline int printf(const char *fmt, ...) {
va_list ap;
int ret;
va_start(ap, fmt);
ret = vfprintf(stdout, fmt, ap);
va_end(ap);
return ret;
}
#v-

I would assume such definitions in header file to be valid and
conforming and if those were used one wouldn't be allowed to do:

#v+
int main(void) {
extern int printf(const char *, ...);
printf("hello, world\n");
return 0;
}
#v-

This of course holds for all other functions.

--
Best regards, _ _
.o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o
..o | Computer Science, Michal "mina86" Nazarewicz (o o)
ooo +--<mina86*tlen.pl>--<jid:mina86*jabber.org>--ooO--(_)--Ooo--

Ben Bacarisse

unread,
Mar 9, 2010, 7:56:38 AM3/9/10
to
Michal Nazarewicz <min...@tlen.pl> writes:

> Debanjan <debanj...@gmail.com> writes:
>> To be precise I was asked to print the month for a corresponding
>> integer using standard library function, but not allowed to include
>> any header file.
>
> At this point I started wondering whether it is guaranteed that
> functions like printf(), time(), etc. have external linkage.

Yes. 7.1.2 p6: "Any declaration of a library function shall have
external linkage."

To be sure you need some other facts like the fact the headers really
do declare functions, but those bases are covered one way or another.

<snip>
--
Ben.

Richard Bos

unread,
Mar 10, 2010, 9:14:13 AM3/10/10
to
Keith Thompson <ks...@mib.org> wrote:

> "Default User" <defaul...@yahoo.com> writes:
> > Seebs wrote:
> >> Sounds like a pretty bad interview question to me.
> >
> > Sounds like a terrific one to me. You can just get up, shake his hand,
> > and leave without wasting any more of your time.
>
> Or you can tell the interviewer that it's a very silly thing to do,
> and he can tell you that was the answer he was looking for.

And then you can tell him that you'd prefer your employer not to be
trying to set traps for his employees.

Really, if _you_ would do that to _him_, you'd never get hired. Why
should he be allowed any more dishonesty than you?

Richard

Keith Thompson

unread,
Mar 10, 2010, 12:37:02 PM3/10/10
to

In a real job, you're likely to be faced with bad requirements.
As an interviewer, how would you judge an applicant's ability and
willingness to question such requirements?

Default User

unread,
Mar 10, 2010, 5:23:25 PM3/10/10
to
Keith Thompson wrote:

> ral...@xs4all.nl (Richard Bos) writes:
> > Keith Thompson <ks...@mib.org> wrote:
> >> "Default User" <defaul...@yahoo.com> writes:
> >> > Seebs wrote:
> >> >> Sounds like a pretty bad interview question to me.
> >> >
> >> > Sounds like a terrific one to me. You can just get up, shake his
> hand, >> > and leave without wasting any more of your time.
> >>
> >> Or you can tell the interviewer that it's a very silly thing to do,
> >> and he can tell you that was the answer he was looking for.
> >
> > And then you can tell him that you'd prefer your employer not to be
> > trying to set traps for his employees.
> >

> > Really, if you would do that to him, you'd never get hired. Why


> > should he be allowed any more dishonesty than you?
>
> In a real job, you're likely to be faced with bad requirements.
> As an interviewer, how would you judge an applicant's ability and
> willingness to question such requirements?

That's true, but irrelevant. The requirements in a real job should not
be a deliberate trap to see what the reaction will be.

In the given case, the applicant has no way of knowing a trap has been
set. The best he or she can do is assume that this is a legitimate
question. Given that assumption, then the only reasonable conclusion is
that it's a clueless question that indicates a clueless interviewer,
futher indicating a clueless organization.

Like I said, get up and leave. Whether it's a dumb question or a trap
doesn't matter.


Brian

--
Day 400 of the "no grouchy usenet posts" project

Keith Thompson

unread,
Mar 10, 2010, 7:13:14 PM3/10/10
to
"Default User" <defaul...@yahoo.com> writes:
> Keith Thompson wrote:
>> ral...@xs4all.nl (Richard Bos) writes:
>> > Keith Thompson <ks...@mib.org> wrote:
>> >> "Default User" <defaul...@yahoo.com> writes:
>> >> > Seebs wrote:
>> >> >> Sounds like a pretty bad interview question to me.
>> >> >
>> >> > Sounds like a terrific one to me. You can just get up, shake his
>> hand, >> > and leave without wasting any more of your time.
>> >>
>> >> Or you can tell the interviewer that it's a very silly thing to do,
>> >> and he can tell you that was the answer he was looking for.
>> >
>> > And then you can tell him that you'd prefer your employer not to be
>> > trying to set traps for his employees.
>> >
>> > Really, if you would do that to him, you'd never get hired. Why
>> > should he be allowed any more dishonesty than you?
>>
>> In a real job, you're likely to be faced with bad requirements.
>> As an interviewer, how would you judge an applicant's ability and
>> willingness to question such requirements?
>
> That's true, but irrelevant. The requirements in a real job should not
> be a deliberate trap to see what the reaction will be.

That doesn't answer the question. Being able to respond reasonably
to unreasonable requirements is a valuable skill. How do you test
that in the course of an interview?

And I wouldn't say this is necessarily a trap. If I were an
interviewer, I'd give the applicant some credit for giving a
reasonably good answer that conforms to the requirements. I'd give
even more credit for pointing out the problem with the requirements.

You could even phrase the question in a way that avoids any question
of dishonesty, such as "How would you respond to a requirement
like this?".

> In the given case, the applicant has no way of knowing a trap has been
> set. The best he or she can do is assume that this is a legitimate
> question. Given that assumption, then the only reasonable conclusion is
> that it's a clueless question that indicates a clueless interviewer,
> futher indicating a clueless organization.

The best he or she can do is *ask*.

> Like I said, get up and leave. Whether it's a dumb question or a trap
> doesn't matter.

--

Nick Keighley

unread,
Mar 11, 2010, 5:09:14 AM3/11/10
to
On 5 Mar, 20:08, Debanjan <debanjan4...@gmail.com> wrote:

interview question 1:


> Does there exist any other alternative data structure instead of
> struct tm (having same memory allocated as this structure) ? So that I
> could use strftime without declaring <time.h>

interview question 2:
how would you change a car tyre using only your teeth?

Default User

unread,
Mar 11, 2010, 4:09:49 PM3/11/10
to
Keith Thompson wrote:

> "Default User" <defaul...@yahoo.com> writes:

> > That's true, but irrelevant. The requirements in a real job should
> > not be a deliberate trap to see what the reaction will be.
>
> That doesn't answer the question. Being able to respond reasonably
> to unreasonable requirements is a valuable skill. How do you test
> that in the course of an interview?

There's no indication that it's supposed to be an unreasonable
requirement. If you think it is, and the interviewer thinks it's just
dandy, then you fail anyway.

> And I wouldn't say this is necessarily a trap. If I were an
> interviewer, I'd give the applicant some credit for giving a
> reasonably good answer that conforms to the requirements. I'd give
> even more credit for pointing out the problem with the requirements.

The evidence at hand is that the interviewer is incompetent. You have
to assume a trap to come around to a competent interviewer. So either
it's a trap or the interviewer is unqualified to interview. Either way,
I'm out of there.

Brian


--
Day 401 of the "no grouchy usenet posts" project

Andrew Poelstra

unread,
Mar 11, 2010, 4:12:51 PM3/11/10
to
On 2010-03-11, Default User <defaul...@yahoo.com> wrote:
>
> The evidence at hand is that the interviewer is incompetent. You have
> to assume a trap to come around to a competent interviewer. So either
> it's a trap or the interviewer is unqualified to interview. Either way,
> I'm out of there.
>

I once had an employer ask if I knew Java, and the correct
answer (which I got) was "no". The company did a lot of
embedded development and he wanted to make sure I could
manage memory (or at least knew I was supposed to).

--
Andrew Poelstra
http://www.wpsoftware.net/andrew

Keith Thompson

unread,
Mar 11, 2010, 4:26:59 PM3/11/10
to
"Default User" <defaul...@yahoo.com> writes:
> Keith Thompson wrote:
>> "Default User" <defaul...@yahoo.com> writes:
>> > That's true, but irrelevant. The requirements in a real job should
>> > not be a deliberate trap to see what the reaction will be.
>>
>> That doesn't answer the question. Being able to respond reasonably
>> to unreasonable requirements is a valuable skill. How do you test
>> that in the course of an interview?
>
> There's no indication that it's supposed to be an unreasonable
> requirement.

I agree that, based on the limited information we have so far,
it's likely that the interviewer's question was bad, but not
deliberately so. To put it more harshly, the interviewer thought
it was a good question, but only because he was incompetent.

> If you think it is, and the interviewer thinks it's just
> dandy, then you fail anyway.

If I'm right and the interviewer is wrong, and I'm unable to convince
him of that, then yes, I lose. There's not much to be done about
that (unless you're willing to lie and tell the interviewer what
he wants to hear; I'm not).

>> And I wouldn't say this is necessarily a trap. If I were an
>> interviewer, I'd give the applicant some credit for giving a
>> reasonably good answer that conforms to the requirements. I'd give
>> even more credit for pointing out the problem with the requirements.
>
> The evidence at hand is that the interviewer is incompetent. You have
> to assume a trap to come around to a competent interviewer. So either
> it's a trap or the interviewer is unqualified to interview. Either way,
> I'm out of there.

Let's forget about this particular question for a moment.

In the real world, the ability to recognize bad requirements (and
to bring them to the attention of whoever generated them with
the goal of fixing them) is a valuable skill for a programmer.
You're typically not going to be asked to judge the quality of the
requirements; it's going to require some initiative. If you were
an interviewer, how would you test candidates for this ability?

Default User

unread,
Mar 11, 2010, 4:56:35 PM3/11/10
to
Keith Thompson wrote:


> Let's forget about this particular question for a moment.
>
> In the real world, the ability to recognize bad requirements (and
> to bring them to the attention of whoever generated them with
> the goal of fixing them) is a valuable skill for a programmer.

Yes, but that normally consists of getting with the architech and the
requirements writer(s) and going over concerns.

> You're typically not going to be asked to judge the quality of the
> requirements; it's going to require some initiative. If you were
> an interviewer, how would you test candidates for this ability?

You'd present a list of requirements, and ask what the sort of
evaluation the programmer would do prior to starting the job. Ask for
any concerns with the requirements as shown and explanations of why
there would be a concern.

If you want to test something, test it. Don't hide it in another test.

Tim Rentsch

unread,
Mar 23, 2010, 9:22:44 AM3/23/10
to
Eric Sosman <eso...@ieee-dot-org.invalid> writes:

> On 3/6/2010 10:54 AM, Tim Rentsch wrote:
>> Eric Sosman<eso...@ieee-dot-org.invalid> writes:
>>

>>> On 3/6/2010 9:48 AM, Tim Rentsch wrote:
>>>> Eric Sosman<eso...@ieee-dot-org.invalid> writes:
>>>>>

>>>>> Hmmm: It occurs to me that if he knew the size, or an
>>>>> upper bound on the size, he could dodge the alignment issue
>>>>> by obtaining the memory from malloc() (declared free-hand).
>>>>> [snip]
>>>>
>>>> If you use malloc this way, and without including any Standard
>>>> header, you run the risk of undefined behavior. Arguably the
>>>> risk of UB is 100%, but certainly it is non-zero.
>>>
>>> ITYM "< 100%", but I see what you're getting at: If size_t
>>> is narrower than int, you can't call malloc() correctly without
>>> a prototype in scope -- and you can't write the prototype
>>> without a declaration of size_t, which you can only get from
>>> a header.
>>
>> Actually I did mean (arguably) == 100% rather than< 100%, but you
>> got the main point I was making. (The question is whether 7.1.4p2
>> can be satisfied at all without reference to 'size_t'; if 7.1.4p2
>> can't be satisfied, I believe UB is guaranteed.)
>
> The implementation defines whether size_t promotes to int
> or does not. If it doesn't promote, you can write a free-hand
> prototypeless declaration of malloc() and you can call it with
> a single size_t argument (derived from sizeof, since we don't
> know how to declare size_t), and the behavior is well-defined.
> If size_t promotes, it's impossible to call unprototyped malloc()
> correctly, and the behavior is undefined.
>
> So it's implementation-defined whether it's defined or
> undefined. ;-)

Sorry, I guess my earlier comments were too elliptical. I believe
your analysis is correct, but only if we assume the condition in
7.1.4p2 can be satisfied by a declaration with no parameter list.

The issue is, how is the clause "Provided that a library function
can be declared without reference to any type defined in a header"
to be interpreted? Two possible interpretations are:

(a) provided it can be declared exactly as it is specified in
the Standard (that is, with a prototype);

(b) provided it can be declared (either with or without a
prototype) so that calls may be performed without undefined
behavior.

The analysis you give presumes interpretation (b), yes? But it's
possible that interpretation (a) is what was intended, in which
case it would always be undefined behavior to call malloc()
without including the standard header that declares it.

I think there are plausible arguments for either interpretation,
which is why I said earlier "Arguably the risk of UB is 100%".

Tim Rentsch

unread,
Mar 23, 2010, 9:39:22 AM3/23/10
to
Keith Thompson <ks...@mib.org> writes:

> Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> writes:
>> Eric Sosman <eso...@ieee-dot-org.invalid> writes:
>>> On 3/6/2010 9:48 AM, Tim Rentsch wrote:
>>>> Eric Sosman<eso...@ieee-dot-org.invalid> writes:
>>>>> Hmmm: It occurs to me that if he knew the size, or an
>>>>> upper bound on the size, he could dodge the alignment issue
>>>>> by obtaining the memory from malloc() (declared free-hand).
>>>>> [snip]
>>>>
>>>> If you use malloc this way, and without including any Standard
>>>> header, you run the risk of undefined behavior. Arguably the
>>>> risk of UB is 100%, but certainly it is non-zero.
>>>
>>> ITYM "< 100%", but I see what you're getting at: If size_t
>>> is narrower than int, you can't call malloc() correctly without
>>> a prototype in scope -- and you can't write the prototype
>>> without a declaration of size_t, which you can only get from
>>> a header.
>>
>> Actually I did mean (arguably) == 100% rather than < 100%, but you
>> got the main point I was making. (The question is whether 7.1.4p2
>> can be satisfied at all without reference to 'size_t'; if 7.1.4p2
>> can't be satisfied, I believe UB is guaranteed.)
>

> I think that, if you happen to know that size_t is a typedef for, say,
> unsigned long on a given implementation, you can safely declare
>
> void *malloc(unsigned long size);
>
> and call it with no risk of UB *for that implementation*. If size_t
> is declared as
>
> typedef unsigned long size_t;
>
> then size_t isn't just another type that looks like unsigned long; it
> *is* unsigned long (or rather, it's another name for unsigned long).

Perhaps so, but again I think it depends on what the statement in
7.1.4p2 is interpreted to require. If we assume any compatible
declaration works, then what you say is right (and in fact it should
work equally well for, eg, 'unsigned short' if that's what size_t is
in that implementation. But it's possible that 7.1.4p2 was intended
to mean that the function must be declared exactly as it is given
in the Standard (and typedef's are irrelevant). I don't mean to
argue that either interpretation is better than the other, just
that both are possible or plausible given the loose wording.

> Of course it's silly and dangerous to do this rather than just
> #including the proper header unless you're forced to work around a
> broken implementation.

Yes, or working with a freestanding implementation.

Tim Rentsch

unread,
Mar 23, 2010, 9:43:28 AM3/23/10
to
Seebs <usenet...@seebs.net> writes:

> On 2010-03-07, Eric Sosman <eso...@ieee-dot-org.invalid> wrote:
>> On my machine, sizeof(unsigned int) == sizeof(size_t) and
>> sizeof(unsigned long) == sizeof(size_t). Which of unsigned int
>> and unsigned long (if either) actually *is* size_t?
>
>> (It so happens that unsigned int and unsigned long and size_t
>> values are all passed to and from functions with identical code,
>> so -- on my machine -- the resulting undefined behavior would
>> turn out to be "what you wanted." Doesn't make it right, though.)
>
> My guess would be that, on 95% or more of systems (99.9% if we count
> "number of machines you'll encounter", possibly lower if we count each
> distinct system type only once), it would turn out that they would be
> interchangeable -- in that it would never cause a problem to use one
> where the other is expected, or specify the wrong one in a prototype.
>
> Not saying it's not undefined behavior, but in practice I think it is
> very likely to do what the user intends.

Given the current trend towards 64-bit systems, I suspect
those numbers are getting noticeably lower with time.

Seebs

unread,
Mar 23, 2010, 12:12:17 PM3/23/10
to
On 2010-03-23, Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> wrote:
> Seebs <usenet...@seebs.net> writes:
>> On 2010-03-07, Eric Sosman <eso...@ieee-dot-org.invalid> wrote:
>>> (It so happens that unsigned int and unsigned long and size_t
>>> values are all passed to and from functions with identical code,
>>> so -- on my machine -- the resulting undefined behavior would
>>> turn out to be "what you wanted." Doesn't make it right, though.)

>> My guess would be that, on 95% or more of systems (99.9% if we count
>> "number of machines you'll encounter", possibly lower if we count each
>> distinct system type only once), it would turn out that they would be
>> interchangeable -- in that it would never cause a problem to use one
>> where the other is expected, or specify the wrong one in a prototype.

> Given the current trend towards 64-bit systems, I suspect


> those numbers are getting noticeably lower with time.

I misread Eric's post.

... But come to think of it, even pretending he said what I thought he
said, that wasn't a remotely reasonable evaluation.

I've had pretty good luck with casting size_t to unsigned long and using
%lu to print it. But then, I work only with pretty small objects.

Tim Rentsch

unread,
Mar 26, 2010, 9:25:55 AM3/26/10
to
Seebs <usenet...@seebs.net> writes:

> On 2010-03-23, Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> wrote:
>> Seebs <usenet...@seebs.net> writes:
>>> On 2010-03-07, Eric Sosman <eso...@ieee-dot-org.invalid> wrote:
>>>> (It so happens that unsigned int and unsigned long and size_t
>>>> values are all passed to and from functions with identical code,
>>>> so -- on my machine -- the resulting undefined behavior would
>>>> turn out to be "what you wanted." Doesn't make it right, though.)
>
>>> My guess would be that, on 95% or more of systems (99.9% if we count
>>> "number of machines you'll encounter", possibly lower if we count each
>>> distinct system type only once), it would turn out that they would be
>>> interchangeable -- in that it would never cause a problem to use one
>>> where the other is expected, or specify the wrong one in a prototype.
>
>> Given the current trend towards 64-bit systems, I suspect
>> those numbers are getting noticeably lower with time.
>
> I misread Eric's post.
>
> ... But come to think of it, even pretending he said what I thought he
> said, that wasn't a remotely reasonable evaluation.
>
> I've had pretty good luck with casting size_t to unsigned long and using
> %lu to print it. But then, I work only with pretty small objects.

I think that's a good heuristic. And you can protect against
it failing easily enough by an initialization-time assertion
comparing SIZE_MAX and ULONG_MAX.

Keith Thompson

unread,
Mar 26, 2010, 12:23:08 PM3/26/10
to
Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> writes:
> Seebs <usenet...@seebs.net> writes:
[...]

>> I've had pretty good luck with casting size_t to unsigned long and using
>> %lu to print it. But then, I work only with pretty small objects.
>
> I think that's a good heuristic. And you can protect against
> it failing easily enough by an initialization-time assertion
> comparing SIZE_MAX and ULONG_MAX.

Yes, but that might be overkill. Even if SIZE_MAX > ULONG_MAX
(say, unsigned long is 32 bits and size_t is 64 bits), this:

printf("size = %lu\n", (void*)size);

will work correctly as long as the current value of "size" doesn't
exceed ULONG_MAX. And even then, the conversion is well defined, so
the worst thing that can happen is incorrect output. Probably the
most common use for printing size_t values is tracing code whose
output is meant only for the developer.

You could even use a function like this (though you have to be a bit
careful because it's not reentrant).

char *size_image(size_t size)
{
static char result[50];
if (size > ULONG_MAX) {
sprintf(result, "[> %lu]", ULONG_MAX);
}
else {
sprintf(result, "%lu", (unsigned long)size);
}
return result;

Ben Bacarisse

unread,
Mar 26, 2010, 1:52:24 PM3/26/10
to
Keith Thompson <ks...@mib.org> writes:
<snip>

> printf("size = %lu\n", (void*)size);

You meant to type: printf("size = %lu\n", (unsigned long)size);

<snip>
--
Ben.

Keith Thompson

unread,
Mar 26, 2010, 1:55:34 PM3/26/10
to

Yes, of course. Thanks.

Tim Rentsch

unread,
Mar 26, 2010, 10:56:36 PM3/26/10
to
Keith Thompson <ks...@mib.org> writes:

> Tim Rentsch <t...@x-alumni2.alumni.caltech.edu> writes:
>> Seebs <usenet...@seebs.net> writes:
> [...]
>>> I've had pretty good luck with casting size_t to unsigned long and using
>>> %lu to print it. But then, I work only with pretty small objects.
>>
>> I think that's a good heuristic. And you can protect against
>> it failing easily enough by an initialization-time assertion
>> comparing SIZE_MAX and ULONG_MAX.
>
> Yes, but that might be overkill. Even if SIZE_MAX > ULONG_MAX
> (say, unsigned long is 32 bits and size_t is 64 bits), this:
>
> printf("size = %lu\n", (void*)size);
>
> will work correctly as long as the current value of "size" doesn't

> exceed ULONG_MAX. [snip elaboration]

Right, the test I gave was conservative, and perhaps overly so
in some cases. There could also be run-time tests on values,
to add one example. However, the simple conservative test
is easy, and will work in a lot of cases, and has the benefit
that it can detect a problem at compile time. I would probably
start with this simple conservative test, and go to a more
elaborate test only after the warning alarm sounded on the
first test (which might never happen).

0 new messages