Why return a static pointer instead of an out parameter?What REALLY happens when you don't free after malloc?C Language: Why do dynamically-allocated objects return a pointer, while statically-allocated objects give you a choice?Returning pointers from the class. Who is responsible for delete?Why does this function accept a `const char*` as a parameter instead just `char*`?Where are Parameter variables stored in memory?Why does GCC generate 15-20% faster code if I optimize for size instead of speed?Using static instead of malloc - C-languageasctime() weird behaviourWhy 2 stars when passing pointer to a string to a functionWhy do arrays in C decay to pointers?

Is a request to book a business flight ticket for a graduate student an unreasonable one?

Why is the ladder of the LM always in the dark side of the LM?

How can I get a player to accept that they should stop trying to pull stunts without thinking them through first?

Is anyone advocating the promotion of homosexuality in UK schools?

Why does wrapping aluminium foil around my food help it keep warm, even though aluminium is a good conductor?

Is there any reason why MCU changed the Snap to Blip

Misspelling my name on my mathematical publications

Why do we need common sense in AI?

How do you move up one folder in Finder?

How are mathematicians paid to do research?

Why return a static pointer instead of an out parameter?

What's the point of having a RAID 1 configuration over incremental backups to a secondary drive?

How do native German speakers usually express skepticism (using even) about a premise?

When an electron changes its spin, or any other intrinsic property, is it still the same electron?

Why isn't pressure filtration popular compared to vacuum filtration?

Addressing unnecessary daily meetings with manager?

Why doesn't sea level show seasonality?

How to say "How long have you had this dream?"

What is this little owl-like bird?

Apex code to find record diff between two dates (to call API only when needed)

Historical experience as a guide to warship design?

Is there any word for "disobedience to God"?

Single word for "refusing to move to next activity unless present one is completed."

A horrible Stockfish chess engine evaluation



Why return a static pointer instead of an out parameter?


What REALLY happens when you don't free after malloc?C Language: Why do dynamically-allocated objects return a pointer, while statically-allocated objects give you a choice?Returning pointers from the class. Who is responsible for delete?Why does this function accept a `const char*` as a parameter instead just `char*`?Where are Parameter variables stored in memory?Why does GCC generate 15-20% faster code if I optimize for size instead of speed?Using static instead of malloc - C-languageasctime() weird behaviourWhy 2 stars when passing pointer to a string to a functionWhy do arrays in C decay to pointers?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








9















char* asctime (const struct tm * timeptr);
char* ctime (const time_t * timer);


I found that many functions inside of time.h return pointers to static variables, which could be altered by any subsequent call to those functions. That means I have to copy the data I just got as a result and it's an extra operation I have to execute and that makes those functions thread-unsafe.



Why was it implemented that way? Wouldn't these signatures be better?



void asctime (char * out, const struct tm * timeptr);
void ctime (char * out, const time_t * timer);


We always have to take decisions during development. I'm just asking why they chose to return a static pointer instead of taking an "out variable" as a parameter.



By the way (this is another question), why don't they allocate their result on the heap? Is it to allow the use of anything instead of malloc or just for efficiency?










share|improve this question



















  • 3





    Just curious, how do you know that they "...return pointers to static variables"?

    – vahancho
    11 hours ago






  • 5





    @vahancho From the Linux man page: "The four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not thread-safe."

    – John Kugelman
    11 hours ago











  • @vahancho the docs say so

    – Caleth
    11 hours ago











  • You can also read the source code of asctime in cplusplus.com/reference/ctime/asctime

    – Agustín Nieto García
    10 hours ago






  • 1





    @AgustínNietoGarcía "It is defined with a behavior equivalent to", not "this is the source"

    – Caleth
    9 hours ago

















9















char* asctime (const struct tm * timeptr);
char* ctime (const time_t * timer);


I found that many functions inside of time.h return pointers to static variables, which could be altered by any subsequent call to those functions. That means I have to copy the data I just got as a result and it's an extra operation I have to execute and that makes those functions thread-unsafe.



Why was it implemented that way? Wouldn't these signatures be better?



void asctime (char * out, const struct tm * timeptr);
void ctime (char * out, const time_t * timer);


We always have to take decisions during development. I'm just asking why they chose to return a static pointer instead of taking an "out variable" as a parameter.



By the way (this is another question), why don't they allocate their result on the heap? Is it to allow the use of anything instead of malloc or just for efficiency?










share|improve this question



















  • 3





    Just curious, how do you know that they "...return pointers to static variables"?

    – vahancho
    11 hours ago






  • 5





    @vahancho From the Linux man page: "The four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not thread-safe."

    – John Kugelman
    11 hours ago











  • @vahancho the docs say so

    – Caleth
    11 hours ago











  • You can also read the source code of asctime in cplusplus.com/reference/ctime/asctime

    – Agustín Nieto García
    10 hours ago






  • 1





    @AgustínNietoGarcía "It is defined with a behavior equivalent to", not "this is the source"

    – Caleth
    9 hours ago













9












9








9


1






char* asctime (const struct tm * timeptr);
char* ctime (const time_t * timer);


I found that many functions inside of time.h return pointers to static variables, which could be altered by any subsequent call to those functions. That means I have to copy the data I just got as a result and it's an extra operation I have to execute and that makes those functions thread-unsafe.



Why was it implemented that way? Wouldn't these signatures be better?



void asctime (char * out, const struct tm * timeptr);
void ctime (char * out, const time_t * timer);


We always have to take decisions during development. I'm just asking why they chose to return a static pointer instead of taking an "out variable" as a parameter.



By the way (this is another question), why don't they allocate their result on the heap? Is it to allow the use of anything instead of malloc or just for efficiency?










share|improve this question
















char* asctime (const struct tm * timeptr);
char* ctime (const time_t * timer);


I found that many functions inside of time.h return pointers to static variables, which could be altered by any subsequent call to those functions. That means I have to copy the data I just got as a result and it's an extra operation I have to execute and that makes those functions thread-unsafe.



Why was it implemented that way? Wouldn't these signatures be better?



void asctime (char * out, const struct tm * timeptr);
void ctime (char * out, const time_t * timer);


We always have to take decisions during development. I'm just asking why they chose to return a static pointer instead of taking an "out variable" as a parameter.



By the way (this is another question), why don't they allocate their result on the heap? Is it to allow the use of anything instead of malloc or just for efficiency?







c time.h






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 8 hours ago









Boann

38.3k13 gold badges92 silver badges123 bronze badges




38.3k13 gold badges92 silver badges123 bronze badges










asked 11 hours ago









Agustín Nieto GarcíaAgustín Nieto García

1491 silver badge8 bronze badges




1491 silver badge8 bronze badges







  • 3





    Just curious, how do you know that they "...return pointers to static variables"?

    – vahancho
    11 hours ago






  • 5





    @vahancho From the Linux man page: "The four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not thread-safe."

    – John Kugelman
    11 hours ago











  • @vahancho the docs say so

    – Caleth
    11 hours ago











  • You can also read the source code of asctime in cplusplus.com/reference/ctime/asctime

    – Agustín Nieto García
    10 hours ago






  • 1





    @AgustínNietoGarcía "It is defined with a behavior equivalent to", not "this is the source"

    – Caleth
    9 hours ago












  • 3





    Just curious, how do you know that they "...return pointers to static variables"?

    – vahancho
    11 hours ago






  • 5





    @vahancho From the Linux man page: "The four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not thread-safe."

    – John Kugelman
    11 hours ago











  • @vahancho the docs say so

    – Caleth
    11 hours ago











  • You can also read the source code of asctime in cplusplus.com/reference/ctime/asctime

    – Agustín Nieto García
    10 hours ago






  • 1





    @AgustínNietoGarcía "It is defined with a behavior equivalent to", not "this is the source"

    – Caleth
    9 hours ago







3




3





Just curious, how do you know that they "...return pointers to static variables"?

– vahancho
11 hours ago





Just curious, how do you know that they "...return pointers to static variables"?

– vahancho
11 hours ago




5




5





@vahancho From the Linux man page: "The four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not thread-safe."

– John Kugelman
11 hours ago





@vahancho From the Linux man page: "The four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not thread-safe."

– John Kugelman
11 hours ago













@vahancho the docs say so

– Caleth
11 hours ago





@vahancho the docs say so

– Caleth
11 hours ago













You can also read the source code of asctime in cplusplus.com/reference/ctime/asctime

– Agustín Nieto García
10 hours ago





You can also read the source code of asctime in cplusplus.com/reference/ctime/asctime

– Agustín Nieto García
10 hours ago




1




1





@AgustínNietoGarcía "It is defined with a behavior equivalent to", not "this is the source"

– Caleth
9 hours ago





@AgustínNietoGarcía "It is defined with a behavior equivalent to", not "this is the source"

– Caleth
9 hours ago












4 Answers
4






active

oldest

votes


















11














The specification of the ctime and asctime functions goes back to C89, and things were done a bit different back in those days, mainly because multi-processor systems weren't very common and thus using a static buffer wouldn't cause a big problem.



Most likely, they didn't return dynamically allocated memory because it took extra time, and in those days CPU cycles were harder to come by.



If you're on a POSIX system like Linux, you have two other functions available which are basically what you described as an alternative:



 char *asctime_r(const struct tm *tm, char *buf);
char *ctime_r(const time_t *timep, char *buf);


These function take a pointer to a buffer that can receive the output (and they return a pointer to that same buffer). The _r suffix means "reentrant", meaning it can safely be called either in a multithreaded program or more than once without a sequence point in between.






share|improve this answer




















  • 3





    The other advantage to returning a pointer to a static buffer is that it's impossible to leak the memory, so you can do things like printf("It is now %sn", ctime(time(NULL))).

    – Mark
    2 hours ago


















9















That means I have to copy the data I just got as result




Why do you need to copy it?



Note that even if you copy the data as soon as you get it, you will still be open to races.




Why was it implemented that way?




Because when they were standardized (1989), multi-core/SMT did not exist (they started to appear between 2001 and 2006), so most software wasn't multi-threaded. Therefore, it did not matter much. For reference, even POSIX threads were standardized years later (1996) than these functions.



If you needed something else, you could always use a system-specific function.




why don't they allocate their result on the heap?




Allocating is very expensive.




Is it to allow the use of anything instead of malloc or just for efficiency?




Not sure what you mean by that. The proper way to do this is to pass a pointer to the destination buffer, so that the user chooses what allocation method to use.






share|improve this answer

























  • Multi-core systems appeared in relatively widespread commercial use about 1992. ANSI C was de facto documenting existing codebases which were designed with only single threads of execution in mind. There's also significant pushback against standardizing functions that allocate memory in C itself - note the lack of strdup() in the C standard.

    – Andrew Henle
    10 hours ago












  • @AndrewHenle Wasn't sun4d multi-CPU rather than multi-core/SMT? I thought Sun didn't get into multi-core until the UltraSPARC IV (2004). Note that multi-CPU computers/mainframes have existed since the 60s/70s; but while you can do multi-threading in multi-CPU systems, it was rare as you say (multi-processing was way more common AFAIK, you didn't need to exploit the benefits of the shared L2/3 caches).

    – Acorn
    10 hours ago



















5














You are (almost) describing the _s variants that were added in C11



errno_t ctime_s(char *buffer, rsize_t bufsz, const time_t *time);
errno_t asctime_s(char *buf, rsize_t bufsz, const struct tm *time_ptr);


These write to the specified location, provided it is big enough, and report the error otherwise.



You don't need to malloc the buffers for these calls, as you know char buf[26]; is exactly what is needed.






share|improve this answer




















  • 2





    ... that were added as an optional feature in C11. In practice, few compilers implement these or the other Annex K functions. Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard.

    – John Bollinger
    11 hours ago







  • 2





    @JohnBollinger Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard. It's worse than that. Microsoft's implementation doesn't even conform with the original TR 24731-1 technical report itself, which I presume originated with significant Microsoft input.

    – Andrew Henle
    10 hours ago


















2














C is a product of the early 1970s, and that legacy shows in things like this. strtok also uses a static buffer and is neither thread-safe nor re-entrant.



I've not seen a definitive explanation for why those functions were implemented that way. It may have been to save stack space (128 kB was a lot of very expensive memory at the time), it may have been to avoid runtime checks on the size or validity of the target buffer, etc. C was originally designed for systems programming, so if time calculations were being done a lot, I can see this approach saving a significant number of cycles over the course of the day.



Unfortunately, that's speculation on my part. I agree that passing the target buffer is the better solution, and that should be the path forward.






share|improve this answer

























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56951454%2fwhy-return-a-static-pointer-instead-of-an-out-parameter%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    11














    The specification of the ctime and asctime functions goes back to C89, and things were done a bit different back in those days, mainly because multi-processor systems weren't very common and thus using a static buffer wouldn't cause a big problem.



    Most likely, they didn't return dynamically allocated memory because it took extra time, and in those days CPU cycles were harder to come by.



    If you're on a POSIX system like Linux, you have two other functions available which are basically what you described as an alternative:



     char *asctime_r(const struct tm *tm, char *buf);
    char *ctime_r(const time_t *timep, char *buf);


    These function take a pointer to a buffer that can receive the output (and they return a pointer to that same buffer). The _r suffix means "reentrant", meaning it can safely be called either in a multithreaded program or more than once without a sequence point in between.






    share|improve this answer




















    • 3





      The other advantage to returning a pointer to a static buffer is that it's impossible to leak the memory, so you can do things like printf("It is now %sn", ctime(time(NULL))).

      – Mark
      2 hours ago















    11














    The specification of the ctime and asctime functions goes back to C89, and things were done a bit different back in those days, mainly because multi-processor systems weren't very common and thus using a static buffer wouldn't cause a big problem.



    Most likely, they didn't return dynamically allocated memory because it took extra time, and in those days CPU cycles were harder to come by.



    If you're on a POSIX system like Linux, you have two other functions available which are basically what you described as an alternative:



     char *asctime_r(const struct tm *tm, char *buf);
    char *ctime_r(const time_t *timep, char *buf);


    These function take a pointer to a buffer that can receive the output (and they return a pointer to that same buffer). The _r suffix means "reentrant", meaning it can safely be called either in a multithreaded program or more than once without a sequence point in between.






    share|improve this answer




















    • 3





      The other advantage to returning a pointer to a static buffer is that it's impossible to leak the memory, so you can do things like printf("It is now %sn", ctime(time(NULL))).

      – Mark
      2 hours ago













    11












    11








    11







    The specification of the ctime and asctime functions goes back to C89, and things were done a bit different back in those days, mainly because multi-processor systems weren't very common and thus using a static buffer wouldn't cause a big problem.



    Most likely, they didn't return dynamically allocated memory because it took extra time, and in those days CPU cycles were harder to come by.



    If you're on a POSIX system like Linux, you have two other functions available which are basically what you described as an alternative:



     char *asctime_r(const struct tm *tm, char *buf);
    char *ctime_r(const time_t *timep, char *buf);


    These function take a pointer to a buffer that can receive the output (and they return a pointer to that same buffer). The _r suffix means "reentrant", meaning it can safely be called either in a multithreaded program or more than once without a sequence point in between.






    share|improve this answer















    The specification of the ctime and asctime functions goes back to C89, and things were done a bit different back in those days, mainly because multi-processor systems weren't very common and thus using a static buffer wouldn't cause a big problem.



    Most likely, they didn't return dynamically allocated memory because it took extra time, and in those days CPU cycles were harder to come by.



    If you're on a POSIX system like Linux, you have two other functions available which are basically what you described as an alternative:



     char *asctime_r(const struct tm *tm, char *buf);
    char *ctime_r(const time_t *timep, char *buf);


    These function take a pointer to a buffer that can receive the output (and they return a pointer to that same buffer). The _r suffix means "reentrant", meaning it can safely be called either in a multithreaded program or more than once without a sequence point in between.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 6 hours ago

























    answered 11 hours ago









    dbushdbush

    109k15 gold badges120 silver badges154 bronze badges




    109k15 gold badges120 silver badges154 bronze badges







    • 3





      The other advantage to returning a pointer to a static buffer is that it's impossible to leak the memory, so you can do things like printf("It is now %sn", ctime(time(NULL))).

      – Mark
      2 hours ago












    • 3





      The other advantage to returning a pointer to a static buffer is that it's impossible to leak the memory, so you can do things like printf("It is now %sn", ctime(time(NULL))).

      – Mark
      2 hours ago







    3




    3





    The other advantage to returning a pointer to a static buffer is that it's impossible to leak the memory, so you can do things like printf("It is now %sn", ctime(time(NULL))).

    – Mark
    2 hours ago





    The other advantage to returning a pointer to a static buffer is that it's impossible to leak the memory, so you can do things like printf("It is now %sn", ctime(time(NULL))).

    – Mark
    2 hours ago













    9















    That means I have to copy the data I just got as result




    Why do you need to copy it?



    Note that even if you copy the data as soon as you get it, you will still be open to races.




    Why was it implemented that way?




    Because when they were standardized (1989), multi-core/SMT did not exist (they started to appear between 2001 and 2006), so most software wasn't multi-threaded. Therefore, it did not matter much. For reference, even POSIX threads were standardized years later (1996) than these functions.



    If you needed something else, you could always use a system-specific function.




    why don't they allocate their result on the heap?




    Allocating is very expensive.




    Is it to allow the use of anything instead of malloc or just for efficiency?




    Not sure what you mean by that. The proper way to do this is to pass a pointer to the destination buffer, so that the user chooses what allocation method to use.






    share|improve this answer

























    • Multi-core systems appeared in relatively widespread commercial use about 1992. ANSI C was de facto documenting existing codebases which were designed with only single threads of execution in mind. There's also significant pushback against standardizing functions that allocate memory in C itself - note the lack of strdup() in the C standard.

      – Andrew Henle
      10 hours ago












    • @AndrewHenle Wasn't sun4d multi-CPU rather than multi-core/SMT? I thought Sun didn't get into multi-core until the UltraSPARC IV (2004). Note that multi-CPU computers/mainframes have existed since the 60s/70s; but while you can do multi-threading in multi-CPU systems, it was rare as you say (multi-processing was way more common AFAIK, you didn't need to exploit the benefits of the shared L2/3 caches).

      – Acorn
      10 hours ago
















    9















    That means I have to copy the data I just got as result




    Why do you need to copy it?



    Note that even if you copy the data as soon as you get it, you will still be open to races.




    Why was it implemented that way?




    Because when they were standardized (1989), multi-core/SMT did not exist (they started to appear between 2001 and 2006), so most software wasn't multi-threaded. Therefore, it did not matter much. For reference, even POSIX threads were standardized years later (1996) than these functions.



    If you needed something else, you could always use a system-specific function.




    why don't they allocate their result on the heap?




    Allocating is very expensive.




    Is it to allow the use of anything instead of malloc or just for efficiency?




    Not sure what you mean by that. The proper way to do this is to pass a pointer to the destination buffer, so that the user chooses what allocation method to use.






    share|improve this answer

























    • Multi-core systems appeared in relatively widespread commercial use about 1992. ANSI C was de facto documenting existing codebases which were designed with only single threads of execution in mind. There's also significant pushback against standardizing functions that allocate memory in C itself - note the lack of strdup() in the C standard.

      – Andrew Henle
      10 hours ago












    • @AndrewHenle Wasn't sun4d multi-CPU rather than multi-core/SMT? I thought Sun didn't get into multi-core until the UltraSPARC IV (2004). Note that multi-CPU computers/mainframes have existed since the 60s/70s; but while you can do multi-threading in multi-CPU systems, it was rare as you say (multi-processing was way more common AFAIK, you didn't need to exploit the benefits of the shared L2/3 caches).

      – Acorn
      10 hours ago














    9












    9








    9








    That means I have to copy the data I just got as result




    Why do you need to copy it?



    Note that even if you copy the data as soon as you get it, you will still be open to races.




    Why was it implemented that way?




    Because when they were standardized (1989), multi-core/SMT did not exist (they started to appear between 2001 and 2006), so most software wasn't multi-threaded. Therefore, it did not matter much. For reference, even POSIX threads were standardized years later (1996) than these functions.



    If you needed something else, you could always use a system-specific function.




    why don't they allocate their result on the heap?




    Allocating is very expensive.




    Is it to allow the use of anything instead of malloc or just for efficiency?




    Not sure what you mean by that. The proper way to do this is to pass a pointer to the destination buffer, so that the user chooses what allocation method to use.






    share|improve this answer
















    That means I have to copy the data I just got as result




    Why do you need to copy it?



    Note that even if you copy the data as soon as you get it, you will still be open to races.




    Why was it implemented that way?




    Because when they were standardized (1989), multi-core/SMT did not exist (they started to appear between 2001 and 2006), so most software wasn't multi-threaded. Therefore, it did not matter much. For reference, even POSIX threads were standardized years later (1996) than these functions.



    If you needed something else, you could always use a system-specific function.




    why don't they allocate their result on the heap?




    Allocating is very expensive.




    Is it to allow the use of anything instead of malloc or just for efficiency?




    Not sure what you mean by that. The proper way to do this is to pass a pointer to the destination buffer, so that the user chooses what allocation method to use.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 11 hours ago

























    answered 11 hours ago









    AcornAcorn

    9,1852 gold badges18 silver badges46 bronze badges




    9,1852 gold badges18 silver badges46 bronze badges












    • Multi-core systems appeared in relatively widespread commercial use about 1992. ANSI C was de facto documenting existing codebases which were designed with only single threads of execution in mind. There's also significant pushback against standardizing functions that allocate memory in C itself - note the lack of strdup() in the C standard.

      – Andrew Henle
      10 hours ago












    • @AndrewHenle Wasn't sun4d multi-CPU rather than multi-core/SMT? I thought Sun didn't get into multi-core until the UltraSPARC IV (2004). Note that multi-CPU computers/mainframes have existed since the 60s/70s; but while you can do multi-threading in multi-CPU systems, it was rare as you say (multi-processing was way more common AFAIK, you didn't need to exploit the benefits of the shared L2/3 caches).

      – Acorn
      10 hours ago


















    • Multi-core systems appeared in relatively widespread commercial use about 1992. ANSI C was de facto documenting existing codebases which were designed with only single threads of execution in mind. There's also significant pushback against standardizing functions that allocate memory in C itself - note the lack of strdup() in the C standard.

      – Andrew Henle
      10 hours ago












    • @AndrewHenle Wasn't sun4d multi-CPU rather than multi-core/SMT? I thought Sun didn't get into multi-core until the UltraSPARC IV (2004). Note that multi-CPU computers/mainframes have existed since the 60s/70s; but while you can do multi-threading in multi-CPU systems, it was rare as you say (multi-processing was way more common AFAIK, you didn't need to exploit the benefits of the shared L2/3 caches).

      – Acorn
      10 hours ago

















    Multi-core systems appeared in relatively widespread commercial use about 1992. ANSI C was de facto documenting existing codebases which were designed with only single threads of execution in mind. There's also significant pushback against standardizing functions that allocate memory in C itself - note the lack of strdup() in the C standard.

    – Andrew Henle
    10 hours ago






    Multi-core systems appeared in relatively widespread commercial use about 1992. ANSI C was de facto documenting existing codebases which were designed with only single threads of execution in mind. There's also significant pushback against standardizing functions that allocate memory in C itself - note the lack of strdup() in the C standard.

    – Andrew Henle
    10 hours ago














    @AndrewHenle Wasn't sun4d multi-CPU rather than multi-core/SMT? I thought Sun didn't get into multi-core until the UltraSPARC IV (2004). Note that multi-CPU computers/mainframes have existed since the 60s/70s; but while you can do multi-threading in multi-CPU systems, it was rare as you say (multi-processing was way more common AFAIK, you didn't need to exploit the benefits of the shared L2/3 caches).

    – Acorn
    10 hours ago






    @AndrewHenle Wasn't sun4d multi-CPU rather than multi-core/SMT? I thought Sun didn't get into multi-core until the UltraSPARC IV (2004). Note that multi-CPU computers/mainframes have existed since the 60s/70s; but while you can do multi-threading in multi-CPU systems, it was rare as you say (multi-processing was way more common AFAIK, you didn't need to exploit the benefits of the shared L2/3 caches).

    – Acorn
    10 hours ago












    5














    You are (almost) describing the _s variants that were added in C11



    errno_t ctime_s(char *buffer, rsize_t bufsz, const time_t *time);
    errno_t asctime_s(char *buf, rsize_t bufsz, const struct tm *time_ptr);


    These write to the specified location, provided it is big enough, and report the error otherwise.



    You don't need to malloc the buffers for these calls, as you know char buf[26]; is exactly what is needed.






    share|improve this answer




















    • 2





      ... that were added as an optional feature in C11. In practice, few compilers implement these or the other Annex K functions. Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard.

      – John Bollinger
      11 hours ago







    • 2





      @JohnBollinger Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard. It's worse than that. Microsoft's implementation doesn't even conform with the original TR 24731-1 technical report itself, which I presume originated with significant Microsoft input.

      – Andrew Henle
      10 hours ago















    5














    You are (almost) describing the _s variants that were added in C11



    errno_t ctime_s(char *buffer, rsize_t bufsz, const time_t *time);
    errno_t asctime_s(char *buf, rsize_t bufsz, const struct tm *time_ptr);


    These write to the specified location, provided it is big enough, and report the error otherwise.



    You don't need to malloc the buffers for these calls, as you know char buf[26]; is exactly what is needed.






    share|improve this answer




















    • 2





      ... that were added as an optional feature in C11. In practice, few compilers implement these or the other Annex K functions. Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard.

      – John Bollinger
      11 hours ago







    • 2





      @JohnBollinger Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard. It's worse than that. Microsoft's implementation doesn't even conform with the original TR 24731-1 technical report itself, which I presume originated with significant Microsoft input.

      – Andrew Henle
      10 hours ago













    5












    5








    5







    You are (almost) describing the _s variants that were added in C11



    errno_t ctime_s(char *buffer, rsize_t bufsz, const time_t *time);
    errno_t asctime_s(char *buf, rsize_t bufsz, const struct tm *time_ptr);


    These write to the specified location, provided it is big enough, and report the error otherwise.



    You don't need to malloc the buffers for these calls, as you know char buf[26]; is exactly what is needed.






    share|improve this answer















    You are (almost) describing the _s variants that were added in C11



    errno_t ctime_s(char *buffer, rsize_t bufsz, const time_t *time);
    errno_t asctime_s(char *buf, rsize_t bufsz, const struct tm *time_ptr);


    These write to the specified location, provided it is big enough, and report the error otherwise.



    You don't need to malloc the buffers for these calls, as you know char buf[26]; is exactly what is needed.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 11 hours ago

























    answered 11 hours ago









    CalethCaleth

    20.9k2 gold badges23 silver badges44 bronze badges




    20.9k2 gold badges23 silver badges44 bronze badges







    • 2





      ... that were added as an optional feature in C11. In practice, few compilers implement these or the other Annex K functions. Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard.

      – John Bollinger
      11 hours ago







    • 2





      @JohnBollinger Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard. It's worse than that. Microsoft's implementation doesn't even conform with the original TR 24731-1 technical report itself, which I presume originated with significant Microsoft input.

      – Andrew Henle
      10 hours ago












    • 2





      ... that were added as an optional feature in C11. In practice, few compilers implement these or the other Annex K functions. Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard.

      – John Bollinger
      11 hours ago







    • 2





      @JohnBollinger Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard. It's worse than that. Microsoft's implementation doesn't even conform with the original TR 24731-1 technical report itself, which I presume originated with significant Microsoft input.

      – Andrew Henle
      10 hours ago







    2




    2





    ... that were added as an optional feature in C11. In practice, few compilers implement these or the other Annex K functions. Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard.

    – John Bollinger
    11 hours ago






    ... that were added as an optional feature in C11. In practice, few compilers implement these or the other Annex K functions. Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard.

    – John Bollinger
    11 hours ago





    2




    2





    @JohnBollinger Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard. It's worse than that. Microsoft's implementation doesn't even conform with the original TR 24731-1 technical report itself, which I presume originated with significant Microsoft input.

    – Andrew Henle
    10 hours ago





    @JohnBollinger Even Microsoft, the source of that whole boondoggle, doesn't implement the *_s functions fully according to the specifications that were accepted into the language standard. It's worse than that. Microsoft's implementation doesn't even conform with the original TR 24731-1 technical report itself, which I presume originated with significant Microsoft input.

    – Andrew Henle
    10 hours ago











    2














    C is a product of the early 1970s, and that legacy shows in things like this. strtok also uses a static buffer and is neither thread-safe nor re-entrant.



    I've not seen a definitive explanation for why those functions were implemented that way. It may have been to save stack space (128 kB was a lot of very expensive memory at the time), it may have been to avoid runtime checks on the size or validity of the target buffer, etc. C was originally designed for systems programming, so if time calculations were being done a lot, I can see this approach saving a significant number of cycles over the course of the day.



    Unfortunately, that's speculation on my part. I agree that passing the target buffer is the better solution, and that should be the path forward.






    share|improve this answer



























      2














      C is a product of the early 1970s, and that legacy shows in things like this. strtok also uses a static buffer and is neither thread-safe nor re-entrant.



      I've not seen a definitive explanation for why those functions were implemented that way. It may have been to save stack space (128 kB was a lot of very expensive memory at the time), it may have been to avoid runtime checks on the size or validity of the target buffer, etc. C was originally designed for systems programming, so if time calculations were being done a lot, I can see this approach saving a significant number of cycles over the course of the day.



      Unfortunately, that's speculation on my part. I agree that passing the target buffer is the better solution, and that should be the path forward.






      share|improve this answer

























        2












        2








        2







        C is a product of the early 1970s, and that legacy shows in things like this. strtok also uses a static buffer and is neither thread-safe nor re-entrant.



        I've not seen a definitive explanation for why those functions were implemented that way. It may have been to save stack space (128 kB was a lot of very expensive memory at the time), it may have been to avoid runtime checks on the size or validity of the target buffer, etc. C was originally designed for systems programming, so if time calculations were being done a lot, I can see this approach saving a significant number of cycles over the course of the day.



        Unfortunately, that's speculation on my part. I agree that passing the target buffer is the better solution, and that should be the path forward.






        share|improve this answer













        C is a product of the early 1970s, and that legacy shows in things like this. strtok also uses a static buffer and is neither thread-safe nor re-entrant.



        I've not seen a definitive explanation for why those functions were implemented that way. It may have been to save stack space (128 kB was a lot of very expensive memory at the time), it may have been to avoid runtime checks on the size or validity of the target buffer, etc. C was originally designed for systems programming, so if time calculations were being done a lot, I can see this approach saving a significant number of cycles over the course of the day.



        Unfortunately, that's speculation on my part. I agree that passing the target buffer is the better solution, and that should be the path forward.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 8 hours ago









        John BodeJohn Bode

        86.4k14 gold badges86 silver badges155 bronze badges




        86.4k14 gold badges86 silver badges155 bronze badges



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56951454%2fwhy-return-a-static-pointer-instead-of-an-out-parameter%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            Canceling a color specificationRandomly assigning color to Graphics3D objects?Default color for Filling in Mathematica 9Coloring specific elements of sets with a prime modified order in an array plotHow to pick a color differing significantly from the colors already in a given color list?Detection of the text colorColor numbers based on their valueCan color schemes for use with ColorData include opacity specification?My dynamic color schemes

            Invision Community Contents History See also References External links Navigation menuProprietaryinvisioncommunity.comIPS Community ForumsIPS Community Forumsthis blog entry"License Changes, IP.Board 3.4, and the Future""Interview -- Matt Mecham of Ibforums""CEO Invision Power Board, Matt Mecham Is a Liar, Thief!"IPB License Explanation 1.3, 1.3.1, 2.0, and 2.1ArchivedSecurity Fixes, Updates And Enhancements For IPB 1.3.1Archived"New Demo Accounts - Invision Power Services"the original"New Default Skin"the original"Invision Power Board 3.0.0 and Applications Released"the original"Archived copy"the original"Perpetual licenses being done away with""Release Notes - Invision Power Services""Introducing: IPS Community Suite 4!"Invision Community Release Notes

            François Viète Contents Biography Work and thought Bibliography See also Notes Further reading External links Navigation menup. 21Google Bookspp. 75–77Google BooksDe thou (from University of Saint Andrews)ArchivedGoogle BooksGoogle BooksGoogle BooksGoogle booksGoogle Bookscc-parthenay.frL'histoire universelle (fr)Universal History (en)ArchivedAdsabs.harvard.eduPagesperso-orange.frArchive.orgChikara Sasaki. Descartes' mathematical thought p.259Google BooksGoogle BooksGoogle Bookspp. 152 and onwardGoogle BooksGoogle BooksScribd.comGoogle Books1257-7979Google BooksGoogle BooksGoogle BooksGoogle BooksGoogle BooksGoogle BooksGallica.bnf.frGoogle BooksGoogle Books"François Viète"Francois Viète: Father of Modern Algebraic NotationThe Lawyer and the GamblerAbout TarporleySite de Jean-Paul GuichardL'algèbre nouvelle"About the Harmonicon"cb120511976(data)1188044800000 0001 0913 5903n82164680ola2013766880073431702w6vt1sb70287374827140948071409480