Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7832143
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 2, 20262026-06-02T12:03:51+00:00 2026-06-02T12:03:51+00:00

Edit 3: For the code itself all together check the first answer or the

  • 0

Edit 3: For the code itself all together check the first answer or the end of this post.

As stated in the title I’m trying to find a way to tell if an optional argument was passed to a function or not. What I’m trying to do is something like how almost all dynamic languages handle their substring function. Below is mine currently, but it doesn’t work since I don’t know how to tell if/when the thing is used.

char *substring(char *string,unsigned int start, ...){
    va_list args;
    int unsigned i=0;
    long end=-1;
    long long length=strlen(string);
    va_start(args,start);
    end=va_arg(args,int);
    va_end(args);
    if(end==-1){
        end=length;
    }
    char *to_string=malloc(end);
    strncpy(to_string,string+start,end);
    return to_string;
}

Basically I want to still be able to not include the length of the string I want back and just have it go to the end of the string. But I cannot seem to find a way to do this. Since there’s also no way to know the number of arguments passed in C, that took away my first thought of this.

Edit:
new way of doing it here’s the current code.

#define substring(...) P99_CALL_DEFARG(substring, 3, __VA_ARGS__)
#define substring_defarg_2 (0)
char *substring(char *string,unsigned int start, int end){
    int unsigned i=0;
    int num=0;
    long long length=strlen(string);
    if(end==0){
        end=length;
    }
    char *to_string=malloc(length);
    strncpy(to_string,string+start,end);
    return to_string;
}

and then in a file I call test.c to see if it works.

#include "functions.c"
int main(void){
    printf("str:%s",substring("hello world",3,2));
    printf("\nstr2:%s\n",substring("hello world",3));
return 0;
}

functions.c has an include for functions.h which includes everything that is ever needed. Here’s the clang output(since clang seems to usually give a bit more detail.

In file included from ./p99/p99.h:1307:
./p99/p99_generic.h:68:16: warning: '__error__' attribute ignored
__attribute__((__error__("Invalid choice in type generic expression")))
               ^
test.c:4:26: error: called object type 'int' is not a function or function
      pointer
    printf("\nstr2:%s\n",substring("hello world",3));
                         ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from test.c:1:
In file included from ./functions.c:34:
In file included from ./functions.h:50:
./string.c:77:24: note: instantiated from:
#define substring(...) P99_CALL_DEFARG(substring, 3, __VA_ARGS__)

GCC just says the object is not a function

Edit 2: Note that setting it to -1 doesn’t change it either, it still throws the same thing. The compile options I’m using are as follows.

gcc -std=c99 -c test.c -o test -lm -Wall

Clang is the same thing(whether or not it works with it is another question.

ANSWER HERE

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include "p99/p99.h"
#define substring(...) P99_CALL_DEFARG(substring, 3, __VA_ARGS__)
#define substring_defarg_2() (-1)
char *substring(char *string, size_t start, size_t len) {
  size_t length = strlen(string);
  if(len == SIZE_MAX){
    len = length - start;
  }
  char *to_string = malloc(len + 1);
  memcpy(to_string, string+start, len);
  to_string[len] = '\0';
  return to_string;
}

You will need p99 from there. It is by the selected answer. Just drop into your source directory and you should be OK. Also to summarize his answer on the license. You’re able to use it however you want, but you cannot fork it basically. So for this purpose you’re free to use it and the string function in any project whether proprietary or open source.

The only thing I ask is that you at least give a link back to this thread so that others who happen upon it can learn of stack overflow, as that’s how I do my comments for things I’ve gotten help with on here.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-02T12:03:53+00:00Added an answer on June 2, 2026 at 12:03 pm

    Other than common belief functions with optional arguments can be implemented in C, but va_arg functions are not the right tool for such a thing. It can be implemented through va_arg macros, since there are ways to capture the number of arguments that a function receives. The whole thing is a bit tedious to explain and to implement, but you can use P99 for immediate use.

    You’d have to change your function signature to something like

    char *substring(char *string, unsigned int start, int end);
    

    and invent a special code for end if it is omitted at the call side, say -1. Then with P99 you can do

    #include "p99.h"
    
    #define substring(...) P99_CALL_DEFARG(substring, 3, __VA_ARGS__)
    #define substring_defarg_2() (-1)
    

    where you see that you declare a macro that “overloads” your function (yes this is possible, common C library implementations use this all the time) and provide the replacement with the knowledge about the number of arguments your function receives (3 in this case). For each argument for which you want to have a default value you’d then declare the second type of macro with the _defarg_N suffix, N starting at 0.

    The declaration of such macros is not very pretty, but tells at least as much what is going on as the interface of a va_arg function would. The gain is on the caller (“user”) side. There you now can do things like

    substring("Hello", 2); 
    substring("Holla", 2, 2);
    

    to your liking.

    (You’d need a compiler that implements C99 for all of this.)


    Edit: You can even go further than that if you don’t want to implement that convention for end but want to have two distinct functions, instead. You’d implement the two functions:

    char *substring2(char *string, unsigned int start);
    char *substring3(char *string, unsigned int start, unsigned int end);
    

    and then define the macro as

    #define substring(...)                \
     P99_IF_LT(P99_NARG(__VA_ARGS__, 3))  \
     (substring2(__VA_ARGS__))            \
     (substring3(__VA_ARGS__))
    

    this would then ensure that the preprocessor chooses the appropriate function call by looking at the number of arguments it receives.


    Edit2: Here a better suited version of a substring function:

    • use the types that are semantically correct for length and stuff like
      that
    • the third parameter seems to be a length for you and not the end of the string, name it accordingly
    • strncpy is almost never the correct function to chose, there are situations where it doesn’t write the terminating '\0' character. When you know the size of a string use memcpy.

    char *substring(char *string, size_t start, size_t len) {
      size_t length = strlen(string);
      if(len == SIZE_MAX){
        len = length - start;
      }
      char *to_string = malloc(len + 1);
      memcpy(to_string, string+start, len);
      to_string[len] = '\0';
      return to_string;
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

EDIT: This code now works correctly, I only left it in case someone finds
I am getting a StackOverflow Error in this code: EDIT [XmlAttribute(ID)] public string ID
EDIT: My main code no longer works, should this function work? <script type=text/javascript src=jquery-1.7.2.js></script>
As I can't post code I'm asking this as a theoretical question, but giving
Edit--@Uri correctly pointed out that this was an abuse of annotations; trying to actually
As you all know, it's extremely common to have code like this: <a href='#'
EDIT - The code looks strange here, so I suggest viewing the files directly
Edit: Added code (Exception on line 095, 5th time it's hit.) public DataTable ParseBarcodes(String[]
I am supposed edit some code for an assignment, and he gave us the
I have a piece of code: EDIT: The _penParams are initialized as the added

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.