Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C strndup implicit declaration

Tags:

c

I'm trying to use strndup function, but I get the error

error: implicit declaration of function 'strndup' [-Werror=implicit-function-declaration]

I have searched around and found that it's not a standard function and therefore I have to compile with different flags. However, I receive same issue by compiling with the following:

-std=gnu11
-Wall
-Wextra
-Werror
-Wmissing-declarations
-Wmissing-prototypes
-Werror-implicit-function-declaration
-Wreturn-type
-Wparentheses
-Wunused
-Wold-style-definition
-Wundef
-Wshadow
-Wstrict-prototypes
-Wswitch-default
-Wunreachable-code
-D_GNU_SOURCE

I'm doing an assignment and therefore I have to use all these, but what I found is that I have to compile with '-D_GNU_SOURCE' for the error to go away, but it doesn't.

EDIT:

I have these included as well:

#define __STDC_WANT_LIB_EXT2__ 1
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "list.h"

Would very much appreciate help to fix this.

like image 376
Cows42 Avatar asked Sep 02 '17 11:09

Cows42


3 Answers

The functions strdup and strndup are not yet part of Standard C. They are standardized in Posix.1-2008 and declared in <string.h> on Posix systems. Did you include <string.h>?

If your system does not provide these functions, you can define them yourself this way:

#include <string.h>
#include <stdlib.h>

char *strdup(const char *s) {
    size_t size = strlen(s) + 1;
    char *p = malloc(size);
    if (p != NULL) {
        memcpy(p, s, size);
    }
    return p;
}

char *strndup(const char *s, size_t n) {
    char *p;
    size_t n1;

    for (n1 = 0; n1 < n && s[n1] != '\0'; n1++)
        continue;
    p = malloc(n + 1);
    if (p != NULL) {
        memcpy(p, s, n1);
        p[n1] = '\0';
    }
    return p;
}
like image 161
chqrlie Avatar answered Oct 15 '22 07:10

chqrlie


Requesting POSIX functions

You may find that you can 'activate' the declarations of strndup() et al by setting appropriate macros to request POSIX support:

#define _XOPEN_SOURCE 700

That strictly is for the X/Open SUS (Single Unix Specification), but that's usually what you want. Strictly enabling only POSIX functionality would require:

#define _POSIX_C_SOURCE 200809L

The -std=gnu11 compiler option usually enables all these (and other special options) by default, so the fact that you're running into problems suggests you may not have the functions available regardless.

If you don't have strndup() available even with the enabling macros set before you include any headers, you can write your own version of the function. The tricky part is making the declaration available in a suitable header. However, as a band-aid, you could make it static in the only source file that needs it. It is also easiest to implement if you have strnlen() available. If you don't have strnlen() either (a plausible problem), then you need to write that too, but the plain C version probably won't match the speed of an assembler version of strnlen() — or use memchr().

strndup()

char *strndup(const char *str, size_t len)
{
    size_t act = strnlen(str, len);
    char *dst = malloc(act + 1);
    if (dst != 0)
    {
        memmove(dst, str, act);
        dst[act] = '\0';
    }
    return dst;
}

(I note that chqrlie shows a neat alternative using memchr() instead of strnlen().)

strnlen()

size_t strnlen(const char *str, size_t len)
{
    for (size_t size = 0; size < len; size++)
    {
        if (str[size] == '\0')
            return size;
    }
    return len;
}
like image 25
Jonathan Leffler Avatar answered Oct 15 '22 06:10

Jonathan Leffler


Without knowing your code, I guess that you forgot to include string.h.

#include <string.h> 

If you don't include the particular header, the declaration of the function strndup() isn't visible to the compiler. Hence the error message of strndup() not being declared.

Put the above line at the top of your code and it should work.

like image 29
Eduard Itrich Avatar answered Oct 15 '22 07:10

Eduard Itrich