I know that global variables in C sometimes have the extern
keyword. What is an extern
variable? What is the declaration like? What is its scope?
This is related to sharing variables across source files, but how does that work precisely? Where do I use extern
?
0
Using extern
is only of relevance when the program you’re building
consists of multiple source files linked together, where some of the
variables defined, for example, in source file file1.c
need to be
referenced in other source files, such as file2.c
.
It is important to understand the difference between defining a
variable and declaring a
variable:
-
A variable is declared when the compiler is informed that a
variable exists (and this is its type); it does not allocate the
storage for the variable at that point. -
A variable is defined when the compiler allocates the storage for
the variable.
You may declare a variable multiple times (though once is sufficient);
you may only define it once within a given scope.
A variable definition is also a declaration, but not all variable
declarations are definitions.
Best way to declare and define global variables
The clean, reliable way to declare and define global variables is to use
a header file to contain an extern
declaration of the variable.
The header is included by the one source file that defines the variable
and by all the source files that reference the variable.
For each program, one source file (and only one source file) defines the
variable.
Similarly, one header file (and only one header file) should declare the
variable.
The header file is crucial; it enables cross-checking between
independent TUs (translation units — think source files) and ensures
consistency.
Although there are other ways of doing it, this method is simple and
reliable.
It is demonstrated by file3.h
, file1.c
and file2.c
:
file3.h
extern int global_variable; /* Declaration of the variable */
file1.c
#include "file3.h" /* Declaration made available here */
#include "prog1.h" /* Function declarations */
/* Variable defined here */
int global_variable = 37; /* Definition checked against declaration */
int increment(void) { return global_variable++; }
file2.c
#include "file3.h"
#include "prog1.h"
#include <stdio.h>
void use_it(void)
{
printf("Global variable: %dn", global_variable++);
}
That’s the best way to declare and define global variables.
The next two files complete the source for prog1
:
The complete programs shown use functions, so function declarations have
crept in.
Both C99 and C11 require functions to be declared or defined before they
are used (whereas C90 did not, for good reasons).
I use the keyword extern
in front of function declarations in headers
for consistency — to match the extern
in front of variable
declarations in headers.
Many people prefer not to use extern
in front of function
declarations; the compiler doesn’t care — and ultimately, neither do I
as long as you’re consistent, at least within a source file.
prog1.h
extern void use_it(void);
extern int increment(void);
prog1.c
#include "file3.h"
#include "prog1.h"
#include <stdio.h>
int main(void)
{
use_it();
global_variable += 19;
use_it();
printf("Increment: %dn", increment());
return 0;
}
prog1
usesprog1.c
,file1.c
,file2.c
,file3.h
andprog1.h
.
The file prog1.mk
is a makefile for prog1
only.
It will work with most versions of make
produced since about the turn
of the millennium.
It is not tied specifically to GNU Make.
prog1.mk
# Minimal makefile for prog1
PROGRAM = prog1
FILES.c = prog1.c file1.c file2.c
FILES.h = prog1.h file3.h
FILES.o = ${FILES.c:.c=.o}
CC = gcc
SFLAGS = -std=c11
GFLAGS = -g
OFLAGS = -O3
WFLAG1 = -Wall
WFLAG2 = -Wextra
WFLAG3 = -Werror
WFLAG4 = -Wstrict-prototypes
WFLAG5 = -Wmissing-prototypes
WFLAGS = ${WFLAG1} ${WFLAG2} ${WFLAG3} ${WFLAG4} ${WFLAG5}
UFLAGS = # Set on command line only
CFLAGS = ${SFLAGS} ${GFLAGS} ${OFLAGS} ${WFLAGS} ${UFLAGS}
LDFLAGS =
LDLIBS =
all: ${PROGRAM}
${PROGRAM}: ${FILES.o}
${CC} -o $@ ${CFLAGS} ${FILES.o} ${LDFLAGS} ${LDLIBS}
prog1.o: ${FILES.h}
file1.o: ${FILES.h}
file2.o: ${FILES.h}
# If it exists, prog1.dSYM is a directory on macOS
DEBRIS = a.out core *~ *.dSYM
RM_FR = rm -fr
clean:
${RM_FR} ${FILES.o} ${PROGRAM} ${DEBRIS}
Guidelines
Rules to be broken by experts only, and only with good reason:
-
A header file only contains
extern
declarations of variables — never
static
or unqualified variable definitions. -
For any given variable, only one header file declares it (SPOT —
Single Point of Truth). -
A source file never contains
extern
declarations of variables —
source files always include the (sole) header that declares them. -
For any given variable, exactly one source file defines the variable,
preferably initializing it too. (Although there is no need to
initialize explicitly to zero, it does no harm and can do some good,
because there can be only one initialized definition of a particular
global variable in a program). -
The source file that defines the variable also includes the header to
ensure that the definition and the declaration are consistent. -
A function should never need to declare a variable using
extern
. -
Avoid global variables whenever possible — use functions instead.
The source code and text of this answer are available in my
SOQ (Stack Overflow Questions)
repository on GitHub in the
src/so-0143-3204
sub-directory.
If you’re not an experienced C programmer, you could (and perhaps
should) stop reading here.
Not so good way to define global variables
With some (indeed, many) C compilers, you can get away with what’s
called a ‘common’ definition of a variable too.
‘Common’, here, refers to a technique used in Fortran for sharing
variables between source files, using a (possibly named) COMMON block.
What happens here is that each of a number of files provides a tentative
definition of the variable.
As long as no more than one file provides an initialized definition,
then the various files end up sharing a common single definition of the
variable:
file10.c
#include "prog2.h"
long l; /* Do not do this in portable code */
void inc(void) { l++; }
file11.c
#include "prog2.h"
long l; /* Do not do this in portable code */
void dec(void) { l--; }
file12.c
#include "prog2.h"
#include <stdio.h>
long l = 9; /* Do not do this in portable code */
void put(void) { printf("l = %ldn", l); }
This technique does not conform to the letter of the C standard and the
‘one definition rule’ — it is officially undefined behaviour:
J.2 Undefined behavior
An identifier with external linkage is used, but in the program there
does not exist exactly one external definition for the identifier, or
the identifier is not used and there exist multiple external
definitions for the identifier (6.9).
§6.9 External definitions ¶5
An external definition is an external declaration that is also a
definition of a function (other than an inline definition) or an
object.
If an identifier declared with external linkage is used in an
expression (other than as part of the operand of asizeof
or
_Alignof
operator whose result is an integer constant), somewhere in
the entire program there shall be exactly one external definition for
the identifier; otherwise, there shall be no more than
one.161)
161) Thus, if an identifier declared with external linkage
is not used in an expression, there need be no external definition for
it.
However, the C standard also lists it in informative Annex J as one of
the Common extensions.
J.5.11 Multiple external definitions
There may be more than one external definition for the identifier of
an object, with or without the explicit use of the keyword extern; if
the definitions disagree, or more than one is initialized, the
behavior is undefined (6.9.2).
Because this technique is not always supported, it is best to avoid
using it, especially if your code needs to be portable.
Using this technique, you can also end up with unintentional type
punning.
If one of the files above declared l
as a double
instead of as a
long
, C’s type-unsafe linkers probably would not spot the mismatch.
If you’re on a machine with 64-bit long
and double
, you’d not even
get a warning; on a machine with 32-bit long
and 64-bit double
,
you’d probably get a warning about the different sizes — the linker
would use the largest size, exactly as a Fortran program would take the
largest size of any common blocks.
Note that GCC 10.1.0, which was released on 2020-05-07, changes the
default compilation options to use
-fno-common
, which means
that by default, the code above no longer links unless you override the
default with -fcommon
(or use attributes, etc — see the link).
The next two files complete the source for prog2
:
prog2.h
extern void dec(void);
extern void put(void);
extern void inc(void);
prog2.c
#include "prog2.h"
#include <stdio.h>
int main(void)
{
inc();
put();
dec();
put();
dec();
put();
}
prog2
usesprog2.c
,file10.c
,file11.c
,file12.c
,prog2.h
.
Warning
As noted in comments here, and as stated in my answer to a similar
question, using multiple
definitions for a global variable leads to undefined behaviour (J.2;
§6.9), which is the standard’s way of saying “anything could happen”.
One of the things that can happen is that the program behaves as you
expect; and J.5.11 says, approximately, “you might be lucky more often
than you deserve”.
But a program that relies on multiple definitions of an extern variable
— with or without the explicit ‘extern’ keyword — is not a strictly
conforming program and not guaranteed to work everywhere.
Equivalently: it contains a bug which may or may not show itself.
Violating the guidelines
There are, of course, many ways in which these guidelines can be broken.
Occasionally, there may be a good reason to break the guidelines, but
such occasions are extremely unusual.
faulty_header.h
int some_var; /* Do not do this in a header!!! */
Note 1: if the header defines the variable without the extern
keyword,
then each file that includes the header creates a tentative definition
of the variable.
As noted previously, this will often work, but the C standard does not
guarantee that it will work.
broken_header.h
int some_var = 13; /* Only one source file in a program can use this */
Note 2: if the header defines and initializes the variable, then only
one source file in a given program can use the header.
Since headers are primarily for sharing information, it is a bit silly
to create one that can only be used once.
seldom_correct.h
static int hidden_global = 3; /* Each source file gets its own copy */
Note 3: if the header defines a static variable (with or without
initialization), then each source file ends up with its own private
version of the ‘global’ variable.
If the variable is actually a complex array, for example, this can lead
to extreme duplication of code. It can, very occasionally, be a
sensible way to achieve some effect, but that is very unusual.
Summary
Use the header technique I showed first.
It works reliably and everywhere.
Note, in particular, that the header declaring the global_variable
is
included in every file that uses it — including the one that defines it.
This ensures that everything is self-consistent.
Similar concerns arise with declaring and defining functions —
analogous rules apply.
But the question was about variables specifically, so I’ve kept the
answer to variables only.
End of Original Answer
If you’re not an experienced C programmer, you probably should stop reading here.
Late Major Addition
Avoiding Code Duplication
One concern that is sometimes (and legitimately) raised about the
‘declarations in headers, definitions in source’ mechanism described
here is that there are two files to be kept synchronized — the header
and the source. This is usually followed up with an observation that a
macro can be used so that the header serves double duty — normally
declaring the variables, but when a specific macro is set before the
header is included, it defines the variables instead.
Another concern can be that the variables need to be defined in each of
a number of ‘main programs’. This is normally a spurious concern; you
can simply introduce a C source file to define the variables and link
the object file produced with each of the programs.
A typical scheme works like this, using the original global variable
illustrated in file3.h
:
file3a.h
#ifdef DEFINE_VARIABLES
#define EXTERN /* nothing */
#else
#define EXTERN extern
#endif /* DEFINE_VARIABLES */
EXTERN int global_variable;
file1a.c
#define DEFINE_VARIABLES
#include "file3a.h" /* Variable defined - but not initialized */
#include "prog3.h"
int increment(void) { return global_variable++; }
file2a.c
#include "file3a.h"
#include "prog3.h"
#include <stdio.h>
void use_it(void)
{
printf("Global variable: %dn", global_variable++);
}
The next two files complete the source for prog3
:
prog3.h
extern void use_it(void);
extern int increment(void);
prog3.c
#include "file3a.h"
#include "prog3.h"
#include <stdio.h>
int main(void)
{
use_it();
global_variable += 19;
use_it();
printf("Increment: %dn", increment());
return 0;
}
prog3
usesprog3.c
,file1a.c
,file2a.c
,file3a.h
,prog3.h
.
Variable initialization
The problem with this scheme as shown is that it does not provide for
initialization of the global variable. With C99 or C11 and variable argument
lists for macros, you could define a macro to support initialization too.
(With C89 and no support for variable argument lists in macros, there is no
easy way to handle arbitrarily long initializers.)
file3b.h
#ifdef DEFINE_VARIABLES
#define EXTERN /* nothing */
#define INITIALIZER(...) = __VA_ARGS__
#else
#define EXTERN extern
#define INITIALIZER(...) /* nothing */
#endif /* DEFINE_VARIABLES */
EXTERN int global_variable INITIALIZER(37);
EXTERN struct { int a; int b; } oddball_struct INITIALIZER({ 41, 43 });
Reverse contents of #if
and #else
blocks, fixing bug identified by
Denis Kniazhev
file1b.c
#define DEFINE_VARIABLES
#include "file3b.h" /* Variables now defined and initialized */
#include "prog4.h"
int increment(void) { return global_variable++; }
int oddball_value(void) { return oddball_struct.a + oddball_struct.b; }
file2b.c
#include "file3b.h"
#include "prog4.h"
#include <stdio.h>
void use_them(void)
{
printf("Global variable: %dn", global_variable++);
oddball_struct.a += global_variable;
oddball_struct.b -= global_variable / 2;
}
Clearly, the code for the oddball structure is not what you’d normally
write, but it illustrates the point. The first argument to the second
invocation of INITIALIZER
is { 41
and the remaining argument
(singular in this example) is 43 }
. Without C99 or similar support
for variable argument lists for macros, initializers that need to
contain commas are very problematic.
Correct header file3b.h
included (instead of fileba.h
) per
Denis Kniazhev
The next two files complete the source for prog4
:
prog4.h
extern int increment(void);
extern int oddball_value(void);
extern void use_them(void);
prog4.c
#include "file3b.h"
#include "prog4.h"
#include <stdio.h>
int main(void)
{
use_them();
global_variable += 19;
use_them();
printf("Increment: %dn", increment());
printf("Oddball: %dn", oddball_value());
return 0;
}
prog4
usesprog4.c
,file1b.c
,file2b.c
,prog4.h
,file3b.h
.
Header Guards
Any header should be protected against reinclusion, so that type
definitions (enum, struct or union types, or typedefs generally) do not
cause problems. The standard technique is to wrap the body of the
header in a header guard such as:
#ifndef FILE3B_H_INCLUDED
#define FILE3B_H_INCLUDED
...contents of header...
#endif /* FILE3B_H_INCLUDED */
The header might be included twice indirectly. For example, if
file4b.h
includes file3b.h
for a type definition that isn’t shown,
and file1b.c
needs to use both header file4b.h
and file3b.h
, then
you have some more tricky issues to resolve. Clearly, you might revise
the header list to include just file4b.h
. However, you might not be
aware of the internal dependencies — and the code should, ideally,
continue to work.
Further, it starts to get tricky because you might include file4b.h
before including file3b.h
to generate the definitions, but the normal
header guards on file3b.h
would prevent the header being reincluded.
So, you need to include the body of file3b.h
at most once for
declarations, and at most once for definitions, but you might need both
in a single translation unit (TU — a combination of a source file and
the headers it uses).
Multiple inclusion with variable definitions
However, it can be done subject to a not too unreasonable constraint.
Let’s introduce a new set of file names:
-
external.h
for the EXTERN macro definitions, etc. -
file1c.h
to define types (notably,struct oddball
, the type ofoddball_struct
). -
file2c.h
to define or declare the global variables. -
file3c.c
which defines the global variables. -
file4c.c
which simply uses the global variables. -
file5c.c
which shows that you can declare and then define the global variables. -
file6c.c
which shows that you can define and then (attempt to) declare the global variables.
In these examples, file5c.c
and file6c.c
directly include the header
file2c.h
several times, but that is the simplest way to show that the
mechanism works. It means that if the header was indirectly included
twice, it would also be safe.
The restrictions for this to work are:
-
The header defining or declaring the global variables may not itself
define any types. -
Immediately before you include a header that should define variables,
you define the macro DEFINE_VARIABLES. -
The header defining or declaring the variables has stylized contents.
external.h
/*
** This header must not contain header guards (like <assert.h> must not).
** Each time it is invoked, it redefines the macros EXTERN, INITIALIZE
** based on whether macro DEFINE_VARIABLES is currently defined.
*/
#undef EXTERN
#undef INITIALIZE
#ifdef DEFINE_VARIABLES
#define EXTERN /* nothing */
#define INITIALIZE(...) = __VA_ARGS__
#else
#define EXTERN extern
#define INITIALIZE(...) /* nothing */
#endif /* DEFINE_VARIABLES */
file1c.h
#ifndef FILE1C_H_INCLUDED
#define FILE1C_H_INCLUDED
struct oddball
{
int a;
int b;
};
extern void use_them(void);
extern int increment(void);
extern int oddball_value(void);
#endif /* FILE1C_H_INCLUDED */
file2c.h
/* Standard prologue */
#if defined(DEFINE_VARIABLES) && !defined(FILE2C_H_DEFINITIONS)
#undef FILE2C_H_INCLUDED
#endif
#ifndef FILE2C_H_INCLUDED
#define FILE2C_H_INCLUDED
#include "external.h" /* Support macros EXTERN, INITIALIZE */
#include "file1c.h" /* Type definition for struct oddball */
#if !defined(DEFINE_VARIABLES) || !defined(FILE2C_H_DEFINITIONS)
/* Global variable declarations / definitions */
EXTERN int global_variable INITIALIZE(37);
EXTERN struct oddball oddball_struct INITIALIZE({ 41, 43 });
#endif /* !DEFINE_VARIABLES || !FILE2C_H_DEFINITIONS */
/* Standard epilogue */
#ifdef DEFINE_VARIABLES
#define FILE2C_H_DEFINITIONS
#endif /* DEFINE_VARIABLES */
#endif /* FILE2C_H_INCLUDED */
file3c.c
#define DEFINE_VARIABLES
#include "file2c.h" /* Variables now defined and initialized */
int increment(void) { return global_variable++; }
int oddball_value(void) { return oddball_struct.a + oddball_struct.b; }
file4c.c
#include "file2c.h"
#include <stdio.h>
void use_them(void)
{
printf("Global variable: %dn", global_variable++);
oddball_struct.a += global_variable;
oddball_struct.b -= global_variable / 2;
}
file5c.c
#include "file2c.h" /* Declare variables */
#define DEFINE_VARIABLES
#include "file2c.h" /* Variables now defined and initialized */
int increment(void) { return global_variable++; }
int oddball_value(void) { return oddball_struct.a + oddball_struct.b; }
file6c.c
#define DEFINE_VARIABLES
#include "file2c.h" /* Variables now defined and initialized */
#include "file2c.h" /* Declare variables */
int increment(void) { return global_variable++; }
int oddball_value(void) { return oddball_struct.a + oddball_struct.b; }
The next source file completes the source (provides a main program) for prog5
, prog6
and prog7
:
prog5.c
#include "file2c.h"
#include <stdio.h>
int main(void)
{
use_them();
global_variable += 19;
use_them();
printf("Increment: %dn", increment());
printf("Oddball: %dn", oddball_value());
return 0;
}
-
prog5
usesprog5.c
,file3c.c
,file4c.c
,file1c.h
,file2c.h
,external.h
. -
prog6
usesprog5.c
,file5c.c
,file4c.c
,file1c.h
,file2c.h
,external.h
. -
prog7
usesprog5.c
,file6c.c
,file4c.c
,file1c.h
,file2c.h
,external.h
.
This scheme avoids most problems. You only run into a problem if a
header that defines variables (such as file2c.h
) is included by
another header (say file7c.h
) that defines variables. There isn’t an
easy way around that other than “don’t do it”.
You can partially work around the problem by revising file2c.h
into
file2d.h
:
file2d.h
/* Standard prologue */
#if defined(DEFINE_VARIABLES) && !defined(FILE2D_H_DEFINITIONS)
#undef FILE2D_H_INCLUDED
#endif
#ifndef FILE2D_H_INCLUDED
#define FILE2D_H_INCLUDED
#include "external.h" /* Support macros EXTERN, INITIALIZE */
#include "file1c.h" /* Type definition for struct oddball */
#if !defined(DEFINE_VARIABLES) || !defined(FILE2D_H_DEFINITIONS)
/* Global variable declarations / definitions */
EXTERN int global_variable INITIALIZE(37);
EXTERN struct oddball oddball_struct INITIALIZE({ 41, 43 });
#endif /* !DEFINE_VARIABLES || !FILE2D_H_DEFINITIONS */
/* Standard epilogue */
#ifdef DEFINE_VARIABLES
#define FILE2D_H_DEFINITIONS
#undef DEFINE_VARIABLES
#endif /* DEFINE_VARIABLES */
#endif /* FILE2D_H_INCLUDED */
The issue becomes ‘should the header include #undef DEFINE_VARIABLES
?’
If you omit that from the header and wrap any defining invocation with
#define
and #undef
:
#define DEFINE_VARIABLES
#include "file2c.h"
#undef DEFINE_VARIABLES
in the source code (so the headers never alter the value of
DEFINE_VARIABLES
), then you should be clean. It is just a nuisance to
have to remember to write the the extra line. An alternative might be:
#define HEADER_DEFINING_VARIABLES "file2c.h"
#include "externdef.h"
externdef.h
/*
** This header must not contain header guards (like <assert.h> must not).
** Each time it is included, the macro HEADER_DEFINING_VARIABLES should
** be defined with the name (in quotes - or possibly angle brackets) of
** the header to be included that defines variables when the macro
** DEFINE_VARIABLES is defined. See also: external.h (which uses
** DEFINE_VARIABLES and defines macros EXTERN and INITIALIZE
** appropriately).
**
** #define HEADER_DEFINING_VARIABLES "file2c.h"
** #include "externdef.h"
*/
#if defined(HEADER_DEFINING_VARIABLES)
#define DEFINE_VARIABLES
#include HEADER_DEFINING_VARIABLES
#undef DEFINE_VARIABLES
#undef HEADER_DEFINING_VARIABLES
#endif /* HEADER_DEFINING_VARIABLES */
This is getting a tad convoluted, but seems to be secure (using the
file2d.h
, with no #undef DEFINE_VARIABLES
in the file2d.h
).
file7c.c
/* Declare variables */
#include "file2d.h"
/* Define variables */
#define HEADER_DEFINING_VARIABLES "file2d.h"
#include "externdef.h"
/* Declare variables - again */
#include "file2d.h"
/* Define variables - again */
#define HEADER_DEFINING_VARIABLES "file2d.h"
#include "externdef.h"
int increment(void) { return global_variable++; }
int oddball_value(void) { return oddball_struct.a + oddball_struct.b; }
file8c.h
/* Standard prologue */
#if defined(DEFINE_VARIABLES) && !defined(FILE8C_H_DEFINITIONS)
#undef FILE8C_H_INCLUDED
#endif
#ifndef FILE8C_H_INCLUDED
#define FILE8C_H_INCLUDED
#include "external.h" /* Support macros EXTERN, INITIALIZE */
#include "file2d.h" /* struct oddball */
#if !defined(DEFINE_VARIABLES) || !defined(FILE8C_H_DEFINITIONS)
/* Global variable declarations / definitions */
EXTERN struct oddball another INITIALIZE({ 14, 34 });
#endif /* !DEFINE_VARIABLES || !FILE8C_H_DEFINITIONS */
/* Standard epilogue */
#ifdef DEFINE_VARIABLES
#define FILE8C_H_DEFINITIONS
#endif /* DEFINE_VARIABLES */
#endif /* FILE8C_H_INCLUDED */
file8c.c
/* Define variables */
#define HEADER_DEFINING_VARIABLES "file2d.h"
#include "externdef.h"
/* Define variables */
#define HEADER_DEFINING_VARIABLES "file8c.h"
#include "externdef.h"
int increment(void) { return global_variable++; }
int oddball_value(void) { return oddball_struct.a + oddball_struct.b; }
The next two files complete the source for prog8
and prog9
:
prog8.c
#include "file2d.h"
#include <stdio.h>
int main(void)
{
use_them();
global_variable += 19;
use_them();
printf("Increment: %dn", increment());
printf("Oddball: %dn", oddball_value());
return 0;
}
file9c.c
#include "file2d.h"
#include <stdio.h>
void use_them(void)
{
printf("Global variable: %dn", global_variable++);
oddball_struct.a += global_variable;
oddball_struct.b -= global_variable / 2;
}
-
prog8
usesprog8.c
,file7c.c
,file9c.c
. -
prog9
usesprog8.c
,file8c.c
,file9c.c
.
However, the problems are relatively unlikely to occur in practice,
especially if you take the standard advice to
Avoid global variables
Does this exposition miss anything?
_Confession_: The ‘avoiding duplicated code’ scheme outlined here was
developed because the issue affects some code I work on (but don’t own),
and is a niggling concern with the scheme outlined in the first part of
the answer. However, the original scheme leaves you with just two
places to modify to keep variable definitions and declarations
synchronized, which is a big step forward over having exernal variable
declarations scattered throughout the code base (which really matters
when there are thousands of files in total). However, the code in the
files with the names `fileNc.[ch]` (plus `external.h` and `externdef.h`)
shows that it can be made to work. Clearly, it would not be hard to
create a header generator script to give you the standardized template
for a variable defining and declaring header file.
NB These are toy programs with just barely enough code to make them
marginally interesting. There is repetition within the examples that
could be removed, but isn’t to simplify the pedagogical explanation.
(For example: the difference between prog5.c
and prog8.c
is the name
of one of the headers that are included. It would be possible to
reorganize the code so that the main()
function was not repeated, but
it would conceal more than it revealed.)
46
An extern
variable is a declaration (thanks to sbi for the correction) of a variable which is defined in another translation unit. That means the storage for the variable is allocated in another file.
Say you have two .c
-files test1.c
and test2.c
. If you define a global variable int test1_var;
in test1.c
and you’d like to access this variable in test2.c
you have to use extern int test1_var;
in test2.c
.
Complete sample:
$ cat test1.c
int test1_var = 5;
$ cat test2.c
#include <stdio.h>
extern int test1_var;
int main(void) {
printf("test1_var = %dn", test1_var);
return 0;
}
$ gcc test1.c test2.c -o test
$ ./test
test1_var = 5
4
Extern is the keyword you use to declare that the variable itself resides in another translation unit.
So you can decide to use a variable in a translation unit and then access it from another one, then in the second one you declare it as extern and the symbol will be resolved by the linker.
If you don’t declare it as extern you’ll get 2 variables named the same but not related at all, and an error of multiple definitions of the variable.
1
declare | define | initialize |
----------------------------------
extern int a; yes no no
-------------
int a = 2019; yes yes yes
-------------
int a; yes yes no
-------------
Declaration won’t allocate memory (the variable must be defined for memory allocation) but the definition will.
This is just another simple view on the extern keyword since the other answers are really great.
I like to think of an extern variable as a promise that you make to the compiler.
When encountering an extern, the compiler can only find out its type, not where it “lives”, so it can’t resolve the reference.
You are telling it, “Trust me. At link time this reference will be resolvable.”
1
Adding an extern
turns a variable definition into a variable declaration. See this thread as to what’s the difference between a declaration and a definition.
2
extern tells the compiler to trust you that the memory for this variable is declared elsewhere, so it doesnt try to allocate/check memory.
Therefore, you can compile a file that has reference to an extern, but you can not link if that memory is not declared somewhere.
Useful for global variables and libraries, but dangerous because the linker does not type check.
1
The correct interpretation of extern is that you tell something to the compiler. You tell the compiler that, despite not being present right now, the variable declared will somehow be found by the linker (typically in another object (file)). The linker will then be the lucky guy to find everything and put it together, whether you had some extern declarations or not.
extern keyword is used with the variable for its identification as a global variable.
It also represents that you can use the variable declared using extern
keyword in any file though it is declared/defined in other file.
In C a variable inside a file say example.c is given local scope. The compiler expects that the variable would have its definition inside the same file example.c and when it does not find the same , it would throw an error.A function on the other hand has by default global scope . Thus you do not have to explicitly mention to the compiler “look dude…you might find the definition of this function here”. For a function including the file which contains its declaration is enough.(The file which you actually call a header file).
For example consider the following 2 files :
example.c
#include<stdio.h>
extern int a;
main(){
printf("The value of a is <%d>n",a);
}
example1.c
int a = 5;
Now when you compile the two files together, using the following commands :
step 1)cc -o ex example.c example1.c
step 2)./ex
You get the following output : The value of a is <5>
GCC ELF Linux implementation
Other answers have covered the language usage side of view, so now let’s have a look at how it is implemented in this implementation.
main.c
#include <stdio.h>
int not_extern_int = 1;
extern int extern_int;
void main() {
printf("%dn", not_extern_int);
printf("%dn", extern_int);
}
Compile and decompile:
gcc -c main.c
readelf -s main.o
Output contains:
Num: Value Size Type Bind Vis Ndx Name
9: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 not_extern_int
12: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND extern_int
The System V ABI Update ELF spec “Symbol Table” chapter explains:
SHN_UNDEF This section table index means the symbol is undefined. When the link editor combines this object file with another that defines the indicated symbol, this file’s references to the symbol will be linked to the actual definition.
which is basically the behavior the C standard gives to extern
variables.
From now on, it is the job of the linker to make the final program, but the extern
information has already been extracted from the source code into the object file.
Tested on GCC 4.8.
C++17 inline variables
In C++17, you might want to use inline variables instead of extern ones, as they are simple to use (can be defined just once on header) and more powerful (support constexpr). See: What does ‘const static’ mean in C and C++?
3
extern
allows one module of your program to access a global variable or function declared in another module of your program.
You usually have extern variables declared in header files.
If you don’t want a program to access your variables or functions, you use static
which tells the compiler that this variable or function cannot be used outside of this module.
First off, the extern
keyword is not used for defining a variable; rather it is used for declaring a variable. I can say extern
is a storage class, not a data type.
extern
is used to let other C files or external components know this variable is already defined somewhere. Example: if you are building a library, no need to define global variable mandatorily somewhere in library itself. The library will be compiled directly, but while linking the file, it checks for the definition.
extern
simply means a variable is defined elsewhere (e.g., in another file).
0
extern
is used so one first.c
file can have full access to a global parameter in another second.c
file.
The extern
can be declared in the first.c
file or in any of the header files first.c
includes.
1
With xc8 you have to be careful about declaring a variable
as the same type in each file as you could , erroneously,
declare something an int
in one file and a char
say in another.
This could lead to corruption of variables.
This problem was elegantly solved in a microchip forum some 15 years ago
/* See “http:www.htsoft.com” /
/ “forum/all/showflat.php/Cat/0/Number/18766/an/0/page/0#18766”
But this link seems to no longer work…
So I;ll quickly try to explain it;
make a file called global.h.
In it declare the following
#ifdef MAIN_C
#define GLOBAL
/* #warning COMPILING MAIN.C */
#else
#define GLOBAL extern
#endif
GLOBAL unsigned char testing_mode; // example var used in several C files
Now in the file main.c
#define MAIN_C 1
#include "global.h"
#undef MAIN_C
This means in main.c the variable will be declared as an unsigned char
.
Now in other files simply including global.h will
have it declared as an extern for that file.
extern unsigned char testing_mode;
But it will be correctly declared as an unsigned char
.
The old forum post probably explained this a bit more clearly.
But this is a real potential gotcha
when using a compiler
that allows you to declare a variable in one file and then declare it extern as a different type in another. The problems associated with
that are if you say declared testing_mode as an int in another file
it would think it was a 16 bit var and overwrite some other part of ram, potentially corrupting another variable. Difficult to debug!
0
In short extern
means that variable is defined in other module and its address will be known at link time. The compiler does not reserve memory in current module and knows the variable type. To understand extern
is good to have at least little experience with assembler.
extern keyword before a symbol (a var or function) tells the linker that it(the source file) uses an external symbol. This can be seen by running nm -a on such an object file (.o) which uses or assigns a value to a extern var (remember to declare a extern symbol on top like this extern int x or still better, use a header file with extern before vars and functions can be without extern; then in main assign a value to it like this x=5;), i find undefined bss info (letter B written) against such an extern var(symbol). This means x is still unresolved and will be resolved when ld is run (during link-time).
why always use extern in headers?
If i don’t use extern, just declare int x, the declaration becomes sort-of strong and without extern, and this redifines the same variable in every source that includes the header, effectively shadowing the original variable. therefore with just int x in a.h header, I redefine a new global variable x in every source that include this a.h. This var in the source, this without-extern var decl in headers shadows(it doesn’t shadow exactly, it’s redifining a global variable x in every source code that includes the header with just int x, without extern, when i include such header and try to compile .o from such files, every .o has its own definition of this global variable x which was included in the header without extern, and at the time of linking, I get the error multiple definition of variable or symbol x) an important variable defined somewhere of somewhere else in the source files.
Important! it is necessary to use extern before vars in headers.
Functions are already extern by-default.
A very short solution I use to allow a header file to contain the extern reference or actual implementation of an object. The file that actually contains the object just does #define GLOBAL_FOO_IMPLEMENTATION
. Then when I add a new object to this file it shows up in that file also without me having to copy and paste the definition.
I use this pattern across multiple files. So in order to keep things as self contained as possible, I just reuse the single GLOBAL & GLOBALINIT macros in each header. My headers look like this:
//file foo_globals.h
#pragma once
#include "foo.h" //contains Foo typedef
#include <atomic>
#ifdef GLOBAL
#undef GLOBAL
#endif
#ifdef GLOBALINIT
#undef GLOBALINIT
#endif
#ifdef GLOBAL_FOO_IMPLEMENTATION
#define GLOBAL
#define GLOBALINIT(x) = x
#else
#define GLOBAL extern
#define GLOBALINIT(x)
#endif
GLOBAL Foo foo1 GLOBALINIT({2, 3, 4})
GLOBAL std::atomic_bool flag1 GLOBALINIT(true);
GLOBAL std::atomic_uint counter1 GLOBALINIT(5);
//file main.cpp
#define GLOBAL_FOO_IMPLEMENTATION
#include "foo_globals.h"
//file uses_extern_foo.cpp
#include "foo_globals.h
2
Sinh nhật phong cách metal
Tổ chức sinh nhật tại nhà jazz
Dịch vụ sinh nhật xuất sắc hơn
Tiệc sinh nhật cho nhà ngôn ngữ học
Thuê nhóm nhảy metal sinh nhật
Sinh nhật chủ đề sang trọng
Tổ chức sinh nhật tại nhà pop
Dịch vụ sinh nhật hoàn mỹ hơn
Tiệc sinh nhật cho nhà văn học
Trang trí sinh nhật bằng đồ garnet
Sinh nhật phong cách punk rock
Tổ chức sinh nhật tại nhà reggae
Dịch vụ sinh nhật tuyệt vời hơn nữa
Tiệc sinh nhật cho nhà khảo cổ học
Thuê nhóm nhảy punk sinh nhật
Sinh nhật chủ đề ấm cúng
Tổ chức sinh nhật tại nhà blues
Dịch vụ sinh nhật đỉnh cao hơn nữa
Tiệc sinh nhật cho nhà địa lý học
Trang trí sinh nhật bằng đồ aquamarine
Sinh nhật phong cách alternative
Tổ chức sinh nhật tại nhà country
Dịch vụ sinh nhật chất lượng hơn
Tiệc sinh nhật cho nhà thiên văn học
Thuê nhóm nhảy alternative sinh nhật
Sinh nhật chủ đề lãng mạn
Tổ chức sinh nhật tại nhà folk
Dịch vụ sinh nhật sáng chói hơn nữa
Tiệc sinh nhật cho nhà triết học
Trang trí sinh nhật bằng đồ citrine
Sinh nhật phong cách ska
Tổ chức sinh nhật tại nhà techno
Dịch vụ sinh nhật rực rỡ hơn nữa
Tiệc sinh nhật cho nhà kinh tế học
Thuê nhóm nhảy ska sinh nhật
Sinh nhật chủ đề truyền thống
Tổ chức sinh nhật tại nhà electronic
Dịch vụ sinh nhật lung linh hơn nữa
Tiệc sinh nhật cho nhà sử học
Trang trí sinh nhật bằng đồ peridot
Sinh nhật phong cách R&B
Tổ chức sinh nhật tại nhà disco
Dịch vụ sinh nhật đẹp hơn nữa
Tiệc sinh nhật cho nhà nhân học
Thuê nhóm nhảy R&B sinh nhật
Sinh nhật chủ đề phá cách
Tổ chức sinh nhật tại nhà funk
Dịch vụ sinh nhật hoàn toàn hơn nữa
Tiệc sinh nhật cho nhà luật học
Trang trí sinh nhật bằng đồ moonstone
Sinh nhật phong cách gospel
Tổ chức sinh nhật tại nhà soul
Dịch vụ sinh nhật độc đáo hơn nữa
Tiệc sinh nhật cho nhà chính trị học
Thuê nhóm nhảy gospel sinh nhật
Sinh nhật chủ đề nghệ thuật
Tổ chức sinh nhật tại nhà rap
Dịch vụ sinh nhật xuất sắc hơn nữa
Tiệc sinh nhật cho nhà tài chính học
Trang trí sinh nhật bằng đồ onyx
Sinh nhật phong cách hip hop dance
Tổ chức sinh nhật tại nhà indie
Dịch vụ sinh nhật hoàn mỹ hơn nữa
Tiệc sinh nhật cho nhà quản trị học
Thuê nhóm nhảy hip hop sinh nhật
Sinh nhật chủ đề đồng quê
Tổ chức sinh nhật tại nhà acoustic
Dịch vụ sinh nhật tuyệt vời hơn hết
Tiệc sinh nhật cho nhà kỹ thuật học
Trang trí sinh nhật bằng đồ jade
Sinh nhật phong cách breakdance
Tổ chức sinh nhật tại nhà chill
Dịch vụ sinh nhật đỉnh cao hơn hết
Tiệc sinh nhật cho nhà công nghệ học
Thuê nhóm nhảy breakdance sinh nhật
Sinh nhật chủ đề hoàng gia
Tổ chức sinh nhật tại nhà lounge
Dịch vụ sinh nhật chất lượng hơn hết
Tiệc sinh nhật cho nhà nghiên cứu học
Trang trí sinh nhật bằng đồ lapis lazuli
Sinh nhật phong cách street dance
Tổ chức sinh nhật tại nhà classical
Dịch vụ sinh nhật sáng chói hơn hết
Tiệc sinh nhật cho nhà phân tích học
Thuê nhóm nhảy street sinh nhật
Sinh nhật chủ đề huyền bí
Tổ chức sinh nhật tại nhà grunge
Dịch vụ sinh nhật rực rỡ hơn hết
Tiệc sinh nhật cho nhà xã hội học
Trang trí sinh nhật bằng đồ malachite
Sinh nhật phong cách contemporary
Tổ chức sinh nhật tại nhà metal
Dịch vụ sinh nhật lung linh hơn hết
Tiệc sinh nhật cho nhà giáo dục học
Thuê nhóm nhảy contemporary sinh nhật
Sinh nhật chủ đề nhiệt đới
Tổ chức sinh nhật tại nhà punk rock
Dịch vụ sinh nhật đẹp hơn hết
Tiệc sinh nhật cho nhà tâm lý học
Trang trí sinh nhật bằng đồ amber
Sinh nhật phong cách ballet
Tổ chức sinh nhật tại nhà alternative
Dịch vụ sinh nhật hoàn toàn hơn hết
Tiệc sinh nhật cho nhà ngôn ngữ học
Thuê nhóm nhảy ballet sinh nhật
Sinh nhật chủ đề mùa đông
Tổ chức sinh nhật tại nhà ska
Dịch vụ sinh nhật độc đáo hơn hết
Trợ lý AI thông minh nhất cho bạn
Khám phá công nghệ AI tại đây
Trải nghiệm trợ lý ảo tuyệt vời
Công cụ AI hỗ trợ mọi công việc
Tăng năng suất với AI thông minh
AI thay đổi cách bạn làm việc
Trợ lý ảo đáng tin cậy nhất
Khám phá tương lai với AI
Công nghệ AI tiên tiến cho bạn
Hỗ trợ thông minh từ trợ lý AI
AI giúp bạn tiết kiệm thời gian
Trợ lý ảo tốt nhất hiện nay
Công nghệ AI đỉnh cao
Khám phá sức mạnh của AI
Trợ lý AI hỗ trợ 24/7
Công cụ AI cho mọi nhu cầu
AI thông minh, nhanh chóng
Trợ lý ảo dẫn đầu xu hướng
Công nghệ AI dành cho bạn
Hỗ trợ công việc với AI
Trợ lý AI tối ưu hóa công việc
Khám phá AI hiện đại
Công cụ AI đáng kinh ngạc
Trợ lý ảo thông minh vượt trội
AI giúp bạn thành công
Công nghệ AI đáng tin cậy
Trợ lý ảo cho tương lai
Khám phá công cụ AI mới
AI hỗ trợ mọi lúc mọi nơi
Trợ lý ảo thông minh hàng đầu
Công nghệ AI thay đổi cuộc sống
Hỗ trợ tối đa với AI
Trợ lý AI sáng tạo nhất
Công cụ AI mạnh mẽ
Khám phá trợ lý ảo AI
AI thông minh cho mọi người
Trợ lý ảo tối ưu nhất
Công nghệ AI vượt trội
Hỗ trợ công việc bằng AI
Trợ lý AI cho mọi ngành
Khám phá sức mạnh AI
Công cụ AI thông minh nhất
Trợ lý ảo dẫn dắt tương lai
AI hỗ trợ không giới hạn
Công nghệ AI sáng tạo
Trợ lý ảo hiệu quả nhất
Khám phá công nghệ AI đỉnh cao
AI giúp bạn tỏa sáng
Trợ lý ảo thông minh toàn diện
Công cụ AI thay đổi mọi thứ
Trợ lý AI giúp bạn làm việc nhanh hơn
Công nghệ AI hiện đại nhất hiện nay
Trải nghiệm AI thông minh vượt bậc
Công cụ AI hỗ trợ sáng tạo
Trợ lý ảo dành cho mọi nhà
AI tối ưu hóa công việc hàng ngày
Khám phá trợ lý AI tiên tiến
Công nghệ AI cho doanh nghiệp
Trợ lý ảo giúp bạn tiết kiệm sức lực
AI thông minh hỗ trợ cá nhân
Công cụ AI cho tương lai gần
Trợ lý ảo tối ưu mọi tác vụ
Khám phá công nghệ AI độc đáo
AI giúp bạn đạt hiệu quả cao
Trợ lý ảo thông minh và thân thiện
Công nghệ AI dành cho mọi ngành
Trợ lý AI hỗ trợ liên tục
Khám phá sức mạnh AI vượt trội
Công cụ AI giúp bạn nổi bật
Trợ lý ảo cho công việc hiện đại
AI thông minh dẫn đầu thời đại
Công nghệ AI hỗ trợ toàn diện
Trợ lý ảo giúp bạn sáng tạo hơn
Khám phá AI thông minh hàng đầu
Công cụ AI tối ưu cho bạn
Trợ lý AI thay đổi cách làm việc
Công nghệ AI mạnh mẽ và linh hoạt
Trợ lý ảo thông minh cho mọi người
AI hỗ trợ công việc hiệu quả
Khám phá công cụ AI sáng tạo
Trợ lý ảo giúp bạn thành công hơn
Công nghệ AI dẫn dắt tương lai
Trợ lý AI tối ưu cho doanh nghiệp
AI thông minh hỗ trợ mọi lúc
Công cụ AI dành cho sáng tạo
Trợ lý ảo giúp bạn tiết kiệm chi phí
Khám phá trợ lý AI độc quyền
Công nghệ AI thay đổi mọi ngành
Trợ lý AI thông minh cho cuộc sống
AI hỗ trợ công việc nhóm
Công cụ AI hiện đại và mạnh mẽ
Trợ lý ảo tối ưu hóa thời gian
Khám phá sức mạnh AI thông minh
Công nghệ AI cho mọi nhu cầu
Trợ lý AI giúp bạn đi trước thời đại
AI thông minh hỗ trợ cá nhân hóa
Công cụ AI tối ưu cho công việc
Trợ lý ảo dẫn đầu công nghệ
Khám phá AI vượt xa mong đợi
Công nghệ AI sáng tạo không ngừng
Trợ lý AI thông minh và hiệu quả
AI hỗ trợ bạn mọi lúc mọi nơi
Công cụ AI thay đổi cách sống
Trợ lý ảo tối ưu cho tương lai
Khám phá công nghệ AI tiên phong
Công nghệ AI giúp bạn tỏa sáng
Trợ lý AI hỗ trợ công việc sáng tạo
AI thông minh cho mọi lĩnh vực
Công cụ AI dẫn đầu xu hướng
Trợ lý ảo giúp bạn phát triển
Khám phá trợ lý AI mạnh mẽ
Công nghệ AI hỗ trợ không ngừng
Trợ lý AI thông minh cho doanh nhân
AI tối ưu hóa mọi quy trình
Công cụ AI sáng tạo và thông minh
Trợ lý ảo giúp bạn quản lý thời gian
Khám phá sức mạnh của công nghệ AI
Công nghệ AI thay đổi cách nghĩ
Trợ lý AI hỗ trợ mọi dự án
AI thông minh cho cuộc sống hiện đại
Công cụ AI giúp bạn đi xa hơn
Trợ lý ảo tối ưu cho sáng tạo
Khám phá AI thông minh vượt trội
Công nghệ AI dành cho tương lai
Trợ lý AI giúp bạn thành công lớn
AI hỗ trợ công việc hiệu quả hơn
Công cụ AI thông minh và linh hoạt
Trợ lý ảo dẫn đầu mọi xu hướng
Khám phá công nghệ AI sáng tạo
Công nghệ AI tối ưu hóa cuộc sống
Trợ lý AI thông minh cho mọi ngành
AI giúp bạn quản lý công việc
Công cụ AI dành cho thành công
Trợ lý ảo hỗ trợ không giới hạn
Khám phá trợ lý AI thông minh nhất
Công nghệ AI thay đổi mọi thứ
Trợ lý AI tối ưu cho doanh nghiệp
AI thông minh hỗ trợ sáng tạo
Công cụ AI giúp bạn tiết kiệm thời gian
Trợ lý ảo dẫn dắt tương lai
Khám phá sức mạnh AI hiện đại
Công nghệ AI cho mọi người
Trợ lý AI thông minh và đáng tin cậy
AI hỗ trợ bạn vượt qua thử thách
Công cụ AI tối ưu hóa công việc
Trợ lý ảo giúp bạn phát triển nhanh
Khám phá công nghệ AI tiên tiến
Công nghệ AI sáng tạo cho bạn
Trợ lý AI hỗ trợ mọi nhu cầu
AI thông minh thay đổi cuộc chơi
Công cụ AI dẫn đầu mọi lĩnh vực
Trợ lý ảo tối ưu cho mọi tác vụ
Khám phá trợ lý AI vượt trội
Công nghệ AI giúp bạn thành công
Trợ lý AI thông minh cho tương lai
AI hỗ trợ công việc sáng tạo
Công cụ AI thông minh vượt bậc
Trợ lý ảo giúp bạn quản lý hiệu quả
Khám phá sức mạnh AI sáng tạo
Công nghệ AI tối ưu cho cuộc sống
Trợ lý AI thông minh và hiện đại
AI giúp bạn đi trước xu hướng
Công cụ AI hỗ trợ không ngừng
Trợ lý ảo dẫn đầu công nghệ AI
Khám phá công nghệ AI thông minh
Công nghệ AI thay đổi cách làm việc
Trợ lý AI tối ưu hóa sáng tạo
AI thông minh cho mọi công việc
Công cụ AI giúp bạn phát triển
Trợ lý ảo hỗ trợ mọi lúc
Khám phá trợ lý AI tiên phong
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh cho doanh nghiệp
AI giúp bạn tối ưu hóa thời gian
Công cụ AI mạnh mẽ cho bạn
Trợ lý ảo dẫn dắt mọi ngành
Khám phá sức mạnh AI thông minh
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI tối ưu cho sáng tạo
AI thông minh thay đổi tương lai
Công cụ AI giúp bạn thành công hơn
Trợ lý ảo hỗ trợ không giới hạn
Khám phá công nghệ AI hiện đại
Công nghệ AI sáng tạo cho mọi người
Trợ lý AI thông minh vượt mong đợi
AI giúp bạn quản lý công việc tốt hơn
Công cụ AI tối ưu cho doanh nghiệp
Trợ lý ảo dẫn đầu xu hướng công nghệ
Khám phá trợ lý AI sáng tạo
Công nghệ AI hỗ trợ mọi lĩnh vực
Trợ lý AI thông minh cho cuộc sống
AI tối ưu hóa công việc hàng ngày
Công cụ AI giúp bạn đi xa hơn
Trợ lý ảo hỗ trợ mọi nhu cầu
Khám phá sức mạnh AI vượt trội
Công nghệ AI thay đổi cách sống
Trợ lý AI tối ưu cho tương lai
AI thông minh hỗ trợ sáng tạo
Công cụ AI dẫn đầu mọi xu hướng
Trợ lý ảo giúp bạn phát triển nhanh
Khám phá công nghệ AI tiên phong
Công nghệ AI sáng tạo không ngừng
Trợ lý AI thông minh cho doanh nhân
AI giúp bạn tối ưu hóa hiệu suất
Công cụ AI mạnh mẽ và hiệu quả
Trợ lý ảo dẫn dắt tương lai
Khám phá trợ lý AI thông minh
Công nghệ AI hỗ trợ không giới hạn
Trợ lý AI tối ưu cho mọi ngành
AI thông minh thay đổi mọi thứ
Công cụ AI giúp bạn thành công lớn
Trợ lý ảo hỗ trợ mọi lúc mọi nơi
Khám phá sức mạnh AI hiện đại
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh vượt trội
AI giúp bạn quản lý thời gian tốt hơn
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo dẫn đầu công nghệ
Khám phá công nghệ AI vượt bậc
Công nghệ AI hỗ trợ mọi công việc
Trợ lý AI thông minh cho mọi người
AI tối ưu hóa cuộc sống hàng ngày
Công cụ AI giúp bạn phát triển
Trợ lý ảo hỗ trợ không ngừng
Khám phá trợ lý AI tiên tiến
Công nghệ AI sáng tạo và mạnh mẽ
Trợ lý AI thông minh cho doanh nghiệp
AI giúp bạn đi trước thời đại
Công cụ AI tối ưu cho mọi nhu cầu
Trợ lý ảo dẫn dắt mọi xu hướng
Khám phá sức mạnh AI sáng tạo
Công nghệ AI thay đổi cách làm việc
Trợ lý AI thông minh và hiệu quả
AI hỗ trợ bạn vượt qua khó khăn
Công cụ AI giúp bạn tỏa sáng
Trợ lý ảo tối ưu cho công việc
Khám phá công nghệ AI thông minh
Công nghệ AI sáng tạo không giới hạn
Trợ lý AI thông minh cho tương lai
AI giúp bạn quản lý hiệu quả hơn
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo dẫn đầu mọi lĩnh vực
Khám phá trợ lý AI vượt trội
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI thông minh cho mọi ngành
AI tối ưu hóa công việc sáng tạo
Công cụ AI giúp bạn thành công
Trợ lý ảo hỗ trợ mọi lúc
Khám phá sức mạnh AI tiên phong
Công nghệ AI sáng tạo vượt bậc
Trợ lý AI thông minh và mạnh mẽ
AI giúp bạn tối ưu hóa thời gian
Công cụ AI dẫn đầu công nghệ
Trợ lý ảo tối ưu cho doanh nghiệp
Khám phá công nghệ AI hiện đại
Công nghệ AI hỗ trợ không ngừng
Trợ lý AI thông minh cho cuộc sống
AI tối ưu hóa mọi công việc
Công cụ AI giúp bạn phát triển nhanh
Trợ lý ảo dẫn dắt tương lai
Khám phá trợ lý AI sáng tạo
Công nghệ AI thay đổi mọi ngành
Trợ lý AI thông minh vượt trội
AI giúp bạn quản lý công việc
Công cụ AI tối ưu cho sáng tạo
Trợ lý ảo hỗ trợ mọi nhu cầu
Khám phá sức mạnh AI thông minh
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh và hiệu quả
AI tối ưu hóa cuộc sống hiện đại
Công cụ AI giúp bạn đi trước xu hướng
Trợ lý ảo dẫn đầu mọi xu hướng
Khám phá công nghệ AI tiên tiến
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI thông minh cho doanh nghiệp
AI giúp bạn tối ưu hóa công việc
Công cụ AI sáng tạo và mạnh mẽ
Trợ lý ảo tối ưu cho tương lai
Khám phá trợ lý AI vượt bậc
Công nghệ AI thay đổi cách sống
Trợ lý AI thông minh cho mọi người
AI hỗ trợ bạn thành công lớn
Công cụ AI giúp bạn phát triển
Trợ lý ảo dẫn dắt mọi lĩnh vực
Khám phá sức mạnh AI sáng tạo
Công nghệ AI tối ưu cho bạn
Trợ lý AI thông minh và đáng tin cậy
AI giúp bạn quản lý thời gian
Công cụ AI hỗ trợ không giới hạn
Trợ lý ảo tối ưu hóa sáng tạo
Khám phá công nghệ AI thông minh
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh cho doanh nhân
AI tối ưu hóa mọi quy trình
Công cụ AI giúp bạn tỏa sáng
Trợ lý ảo dẫn đầu công nghệ
Khám phá trợ lý AI tiên phong
Công nghệ AI hỗ trợ mọi lúc
Trợ lý AI thông minh vượt mong đợi
AI giúp bạn đi trước thời đại
Công cụ AI tối ưu cho công việc
Trợ lý ảo hỗ trợ không ngừng
Khám phá sức mạnh AI hiện đại
Công nghệ AI sáng tạo cho mọi ngành
Trợ lý AI thông minh và hiệu quả
AI tối ưu hóa cuộc sống hàng ngày
Công cụ AI giúp bạn phát triển nhanh
Trợ lý ảo dẫn dắt tương lai
Khám phá công nghệ AI vượt trội
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI thông minh cho mọi người
AI giúp bạn quản lý công việc
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo hỗ trợ mọi nhu cầu
Khám phá trợ lý AI sáng tạo
Công nghệ AI thay đổi mọi thứ
Trợ lý AI thông minh vượt bậc
AI tối ưu hóa công việc hiệu quả
Công cụ AI giúp bạn thành công
Trợ lý ảo dẫn đầu mọi xu hướng
Khám phá sức mạnh AI thông minh
Công nghệ AI sáng tạo không ngừng
Trợ lý AI thông minh cho doanh nghiệp
AI giúp bạn tối ưu hóa thời gian
Công cụ AI hỗ trợ không giới hạn
Trợ lý ảo tối ưu cho tương lai
Khám phá công nghệ AI tiên tiến
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh và mạnh mẽ
AI tối ưu hóa mọi công việc
Công cụ AI giúp bạn phát triển
Trợ lý ảo dẫn dắt mọi lĩnh vực
Khám phá trợ lý AI vượt trội
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI thông minh cho mọi ngành
AI giúp bạn quản lý hiệu quả
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo hỗ trợ không ngừng
Khám phá sức mạnh AI hiện đại
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh vượt mong đợi
AI tối ưu hóa cuộc sống hiện đại
Công cụ AI giúp bạn đi trước xu hướng
Trợ lý ảo dẫn đầu công nghệ
Khám phá công nghệ AI thông minh
Công nghệ AI hỗ trợ mọi lúc
Trợ lý AI thông minh cho doanh nhân
AI giúp bạn tối ưu hóa công việc
Công cụ AI sáng tạo và hiệu quả
Trợ lý ảo tối ưu cho mọi người
Khám phá trợ lý AI tiên phong
Công nghệ AI thay đổi cách sống
Trợ lý AI thông minh vượt trội
AI tối ưu hóa mọi quy trình
Công cụ AI giúp bạn thành công lớn
Trợ lý ảo dẫn dắt tương lai
Khám phá sức mạnh AI sáng tạo
Công nghệ AI hỗ trợ không giới hạn
Trợ lý AI thông minh cho mọi ngành
AI giúp bạn quản lý thời gian
Công cụ AI tối ưu cho sáng tạo
Trợ lý ảo hỗ trợ mọi nhu cầu
Khám phá công nghệ AI vượt bậc
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh và hiệu quả
AI tối ưu hóa công việc hàng ngày
Công cụ AI giúp bạn phát triển
Trợ lý ảo dẫn đầu mọi xu hướng
Khám phá trợ lý AI thông minh
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI thông minh vượt mong đợi
AI giúp bạn đi trước thời đại
Công cụ AI tối ưu cho doanh nghiệp
Trợ lý ảo hỗ trợ không ngừng
Khám phá sức mạnh AI hiện đại
Công nghệ AI sáng tạo không ngừng
Trợ lý AI thông minh cho mọi người
AI tối ưu hóa mọi công việc
Công cụ AI giúp bạn thành công
Trợ lý ảo dẫn dắt mọi lĩnh vực
Khám phá công nghệ AI tiên tiến
Công nghệ AI hỗ trợ mọi lúc
Trợ lý AI thông minh vượt trội
AI giúp bạn quản lý hiệu quả
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo hỗ trợ không giới hạn
Khám phá trợ lý AI sáng tạo
Công nghệ AI thay đổi cách sống
Trợ lý AI thông minh cho doanh nghiệp
AI tối ưu hóa công việc sáng tạo
Công cụ AI giúp bạn phát triển nhanh
Trợ lý ảo dẫn đầu công nghệ
Khám phá sức mạnh AI vượt bậc
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh và hiệu quả
AI giúp bạn đi trước xu hướng
Công cụ AI tối ưu cho mọi người
Trợ lý ảo hỗ trợ mọi lúc mọi nơi
Khám phá công nghệ AI thông minh
Công nghệ AI hỗ trợ không ngừng
Trợ lý AI thông minh vượt mong đợi
AI tối ưu hóa cuộc sống hiện đại
Công cụ AI giúp bạn thành công lớn
Trợ lý ảo dẫn dắt tương lai
Khám phá trợ lý AI tiên phong
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh cho doanh nhân
AI giúp bạn quản lý thời gian
Công cụ AI tối ưu hóa công việc
Trợ lý ảo hỗ trợ không giới hạn
Khám phá sức mạnh AI sáng tạo
Công nghệ AI thay đổi mọi ngành
Trợ lý AI thông minh và mạnh mẽ
AI tối ưu hóa mọi quy trình
Công cụ AI giúp bạn phát triển
Trợ lý ảo dẫn đầu mọi xu hướng
Khám phá công nghệ AI vượt trội
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI thông minh cho mọi người
AI giúp bạn đi trước thời đại
Công cụ AI tối ưu cho sáng tạo
Trợ lý ảo hỗ trợ mọi lúc
Khám phá trợ lý AI thông minh
Công nghệ AI sáng tạo không ngừng
Trợ lý AI thông minh vượt bậc
AI tối ưu hóa công việc hiệu quả
Công cụ AI giúp bạn thành công
Trợ lý ảo dẫn dắt mọi lĩnh vực
Khám phá sức mạnh AI tiên phong
Công nghệ AI hỗ trợ không giới hạn
Trợ lý AI thông minh cho doanh nghiệp
AI giúp bạn quản lý hiệu quả
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo hỗ trợ mọi nhu cầu
Khám phá công nghệ AI hiện đại
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh và hiệu quả
AI tối ưu hóa cuộc sống hàng ngày
Công cụ AI giúp bạn phát triển nhanh
Trợ lý ảo dẫn đầu công nghệ
Khám phá trợ lý AI vượt trội
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI thông minh vượt mong đợi
AI giúp bạn đi trước xu hướng
Công cụ AI tối ưu cho doanh nghiệp
Trợ lý ảo hỗ trợ không ngừng
Khám phá sức mạnh AI sáng tạo
Công nghệ AI thay đổi mọi thứ
Trợ lý AI thông minh cho mọi người
AI tối ưu hóa mọi công việc
Công cụ AI giúp bạn thành công lớn
Trợ lý ảo dẫn dắt tương lai
Khám phá công nghệ AI tiên phong
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh và mạnh mẽ
AI giúp bạn quản lý thời gian
Công cụ AI tối ưu hóa công việc
Trợ lý ảo hỗ trợ không giới hạn
Khám phá trợ lý AI thông minh
Công nghệ AI hỗ trợ mọi lúc
Trợ lý AI thông minh vượt bậc
AI tối ưu hóa cuộc sống hiện đại
Công cụ AI giúp bạn phát triển
Trợ lý ảo dẫn đầu mọi xu hướng
Khám phá sức mạnh AI vượt trội
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh và hiệu quả
AI giúp bạn đi trước thời đại
Công cụ AI tối ưu cho sáng tạo
Trợ lý ảo hỗ trợ mọi nhu cầu
Khám phá công nghệ AI hiện đại
Công nghệ AI hỗ trợ không ngừng
Trợ lý AI thông minh vượt mong đợi
AI tối ưu hóa mọi quy trình
Công cụ AI giúp bạn thành công
Trợ lý ảo dẫn dắt mọi lĩnh vực
Khám phá trợ lý AI tiên phong
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh cho doanh nghiệp
AI giúp bạn quản lý hiệu quả
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo hỗ trợ không giới hạn
Khám phá sức mạnh AI thông minh
Công nghệ AI thay đổi cách sống
Trợ lý AI thông minh và mạnh mẽ
AI tối ưu hóa công việc hàng ngày
Công cụ AI giúp bạn phát triển nhanh
Trợ lý ảo dẫn đầu công nghệ
Khám phá công nghệ AI vượt bậc
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh vượt trội
AI giúp bạn đi trước xu hướng
Công cụ AI tối ưu cho mọi người
Trợ lý ảo hỗ trợ mọi lúc mọi nơi
Khám phá trợ lý AI thông minh
Công nghệ AI hỗ trợ không ngừng
Trợ lý AI thông minh vượt mong đợi
AI tối ưu hóa cuộc sống hiện đại
Công cụ AI giúp bạn thành công lớn
Trợ lý ảo dẫn dắt tương lai
Khám phá sức mạnh AI tiên phong
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh cho doanh nhân
AI giúp bạn quản lý thời gian
Công cụ AI tối ưu hóa công việc
Trợ lý ảo hỗ trợ không giới hạn
Khám phá công nghệ AI hiện đại
Công nghệ AI hỗ trợ mọi lúc
Trợ lý AI thông minh vượt bậc
AI tối ưu hóa mọi quy trình
Công cụ AI giúp bạn phát triển
Trợ lý ảo dẫn đầu mọi xu hướng
Khám phá trợ lý AI thông minh
Công nghệ AI sáng tạo không ngừng
Trợ lý AI thông minh vượt trội
AI giúp bạn đi trước thời đại
Công cụ AI tối ưu cho sáng tạo
Trợ lý ảo hỗ trợ mọi nhu cầu
Khám phá sức mạnh AI vượt bậc
Công nghệ AI thay đổi cách sống
Trợ lý AI thông minh và hiệu quả
AI tối ưu hóa công việc hàng ngày
Công cụ AI giúp bạn thành công
Trợ lý ảo dẫn dắt mọi lĩnh vực
Khám phá công nghệ AI tiên phong
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh cho doanh nghiệp
AI giúp bạn quản lý hiệu quả
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo hỗ trợ không ngừng
Khám phá trợ lý AI thông minh
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI thông minh vượt mong đợi
AI tối ưu hóa mọi công việc
Công cụ AI giúp bạn phát triển nhanh
Trợ lý ảo dẫn đầu công nghệ
Khám phá sức mạnh AI sáng tạo
Công nghệ AI thay đổi mọi ngành
Trợ lý AI thông minh và mạnh mẽ
AI giúp bạn đi trước xu hướng
Công cụ AI tối ưu cho mọi người
Trợ lý ảo hỗ trợ mọi lúc mọi nơi
Khám phá công nghệ AI vượt trội
Công nghệ AI sáng tạo không ngừng
Trợ lý AI thông minh vượt bậc
AI tối ưu hóa cuộc sống hiện đại
Công cụ AI giúp bạn thành công lớn
Trợ lý ảo dẫn dắt tương lai
Khám phá trợ lý AI tiên phong
Công nghệ AI hỗ trợ không giới hạn
Trợ lý AI thông minh cho doanh nhân
AI giúp bạn quản lý thời gian
Công cụ AI tối ưu hóa công việc
Trợ lý ảo hỗ trợ mọi nhu cầu
Khám phá sức mạnh AI thông minh
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh và hiệu quả
AI tối ưu hóa mọi quy trình
Công cụ AI giúp bạn phát triển
Trợ lý ảo dẫn đầu mọi xu hướng
Khám phá công nghệ AI hiện đại
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI thông minh vượt trội
AI giúp bạn đi trước thời đại
Công cụ AI tối ưu cho sáng tạo
Trợ lý ảo hỗ trợ không ngừng
Khám phá trợ lý AI thông minh
Công nghệ AI sáng tạo vượt bậc
Trợ lý AI thông minh cho doanh nghiệp
AI tối ưu hóa công việc hàng ngày
Công cụ AI giúp bạn thành công
Trợ lý ảo dẫn dắt mọi lĩnh vực
Khám phá sức mạnh AI tiên phong
Công nghệ AI hỗ trợ mọi lúc
Trợ lý AI thông minh vượt mong đợi
AI giúp bạn quản lý hiệu quả
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo hỗ trợ không giới hạn
Khám phá công nghệ AI vượt trội
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh và mạnh mẽ
AI tối ưu hóa mọi công việc
Công cụ AI giúp bạn phát triển nhanh
Trợ lý ảo dẫn đầu công nghệ
Khám phá trợ lý AI thông minh
Công nghệ AI hỗ trợ không ngừng
Trợ lý AI thông minh vượt bậc
AI giúp bạn đi trước xu hướng
Công cụ AI tối ưu cho mọi người
Trợ lý ảo hỗ trợ mọi lúc mọi nơi
Khám phá sức mạnh AI sáng tạo
Công nghệ AI thay đổi cách sống
Trợ lý AI thông minh vượt trội
AI tối ưu hóa cuộc sống hiện đại
Công cụ AI giúp bạn thành công lớn
Trợ lý ảo dẫn dắt tương lai
Khám phá công nghệ AI tiên phong
Công nghệ AI sáng tạo không ngừng
Trợ lý AI thông minh cho doanh nhân
AI giúp bạn quản lý thời gian
Công cụ AI tối ưu hóa công việc
Trợ lý ảo hỗ trợ không giới hạn
Khám phá trợ lý AI thông minh
Công nghệ AI hỗ trợ mọi lúc
Trợ lý AI thông minh vượt mong đợi
AI tối ưu hóa mọi quy trình
Công cụ AI giúp bạn phát triển
Trợ lý ảo dẫn đầu mọi xu hướng
Khám phá sức mạnh AI vượt trội
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh và hiệu quả
AI giúp bạn đi trước thời đại
Công cụ AI tối ưu cho sáng tạo
Trợ lý ảo hỗ trợ mọi nhu cầu
Khám phá công nghệ AI hiện đại
Công nghệ AI hỗ trợ không ngừng
Trợ lý AI thông minh vượt bậc
AI tối ưu hóa công việc hàng ngày
Công cụ AI giúp bạn thành công
Trợ lý ảo dẫn dắt mọi lĩnh vực
Khám phá trợ lý AI tiên phong
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh cho doanh nghiệp
AI giúp bạn quản lý hiệu quả
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo hỗ trợ không giới hạn
Khám phá sức mạnh AI thông minh
Công nghệ AI thay đổi cách sống
Trợ lý AI thông minh và mạnh mẽ
AI tối ưu hóa mọi công việc
Công cụ AI giúp bạn phát triển nhanh
Trợ lý ảo dẫn đầu công nghệ
Khám phá công nghệ AI vượt trội
Công nghệ AI sáng tạo cho bạn
Trợ lý AI thông minh vượt mong đợi
AI giúp bạn đi trước xu hướng
Công cụ AI tối ưu cho mọi người
Trợ lý ảo hỗ trợ mọi lúc mọi nơi
Khám phá trợ lý AI thông minh
Công nghệ AI hỗ trợ không ngừng
Trợ lý AI thông minh vượt bậc
AI tối ưu hóa cuộc sống hiện đại
Công cụ AI giúp bạn thành công lớn
Trợ lý ảo dẫn dắt tương lai
Khám phá sức mạnh AI tiên phong
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh cho doanh nhân
AI giúp bạn quản lý thời gian
Công cụ AI tối ưu hóa công việc
Trợ lý ảo hỗ trợ không giới hạn
Khám phá công nghệ AI hiện đại
Công nghệ AI hỗ trợ mọi lúc
Trợ lý AI thông minh vượt mong đợi
AI tối ưu hóa mọi quy trình
Công cụ AI giúp bạn phát triển
Trợ lý ảo dẫn đầu mọi xu hướng
Khám phá trợ lý AI thông minh
Công nghệ AI sáng tạo không ngừng
Trợ lý AI thông minh vượt trội
AI giúp bạn đi trước thời đại
Công cụ AI tối ưu cho sáng tạo
Trợ lý ảo hỗ trợ mọi nhu cầu
Khám phá sức mạnh AI vượt bậc
Công nghệ AI thay đổi cách sống
Trợ lý AI thông minh và hiệu quả
AI tối ưu hóa công việc hàng ngày
Công cụ AI giúp bạn thành công
Trợ lý ảo dẫn dắt mọi lĩnh vực
Khám phá công nghệ AI tiên phong
Công nghệ AI sáng tạo vượt trội
Trợ lý AI thông minh cho doanh nghiệp
AI giúp bạn quản lý hiệu quả
Công cụ AI tối ưu hóa sáng tạo
Trợ lý ảo hỗ trợ không giới hạn
Khám phá trợ lý AI thông minh
Công nghệ AI hỗ trợ toàn diện
Trợ lý AI thông minh vượt mong đợi
AI tối ưu hóa mọi công việc
Công cụ AI giúp bạn phát triển nhanh
Trợ lý ảo dẫn đầu công nghệ
Khám phá sức mạnh AI sáng tạo
Công nghệ AI thay đổi mọi ngành
Trợ lý AI thông minh và mạnh mẽ
AI giúp bạn đi trước xu hướng
Công cụ AI tối ưu cho mọi người
Trợ lý ảo hỗ trợ mọi lúc mọi nơi
Khám phá công nghệ AI vượt trội
Công nghệ AI sáng tạo không ngừng
Trợ lý AI thông minh vượt bậc
AI tối ưu hóa cuộc sống hiện đại
Công cụ AI giúp bạn thành công lớn
Trợ lý ảo dẫn dắt tương lai
Khám phá trợ lý AI tiên phong
Công nghệ AI hỗ trợ không giới hạn
Trợ lý AI thông minh cho doanh nhân
AI giúp bạn quản lý thời gian
Xổ số miền Nam Kết quả xổ số miền Nam XSMN hôm nay KQXS miền Nam XSMN trực tiếp KQXS hôm nay Xổ số kiến thiết miền Nam Dự đoán XSMN Xổ số miền Nam 24h XSMN chuẩn Kết quả xổ số nhanh Xổ số miền Nam hôm qua XSMN VIP Xổ số miền Nam 7 ngày Xổ số miền Nam chính xác XSMN 3 miền XSMN mới nhất Trực tiếp xổ số miền Nam Xổ số miền Nam hôm nay KQXS miền Nam chính xác Xổ số miền Nam hàng ngày Xổ số miền Nam nhanh nhất Dò vé số miền Nam Xổ số miền Nam chính thống Xổ số kiến thiết Kết quả xổ số miền Nam mới nhất XSMN cực nhanh Thống kê XSMN Dò xổ số miền Nam Xổ số online miền Nam KQXS hôm qua Xổ số nhanh nhất XSMN uy tín KQXS hôm nay nhanh nhất Dự đoán KQXS miền Nam Xổ số siêu tốc Xổ số VIP Xổ số miền Nam 30 ngày Lịch mở thưởng XSMN Xổ số hôm nay XSMN 2025 Dò vé số hôm nay Xổ số miền Nam miễn phí Trực tiếp KQXS miền Nam Dò xổ số nhanh Dự đoán XSMN chuẩn Xổ số 3 miền chính xác Thống kê xổ số miền Nam Dự đoán lô đề XSMN Kết quả XSMN online Kết quả xổ số 3 miền Dò xổ số VIP XSMN miễn phí Xổ số dễ trúng Xổ số miền Nam mỗi ngày Dự đoán XSMN hôm nay Thống kê kết quả XSMN Xổ số miền Nam hôm nay nhanh nhất Xổ số miền Nam mới nhất Xổ số miền Nam hôm qua Dự đoán xổ số miền Nam Đại lý Volvo Bình Thạnh luôn cam kết mang đến dịch vụ và sản phẩm chính hãng. Bạn đang quan tâm đến bảng giá xe Volvo cập nhật mới nhất? Tìm hiểu ngay chính sách mua xe Volvo trả góp cực kỳ ưu đãi và linh hoạt. Khám phá giá xe Volvo EC40 - mẫu xe điện hiện đại, tiết kiệm năng lượng. Nếu bạn yêu thích công nghệ an toàn, đừng bỏ qua Volvo XC60 Ultra đẳng cấp. Dành cho tín đồ xe hybrid, Volvo XC60 Plug-in Hybrid Ultra là lựa chọn đáng cân nhắc. Tham khảo chi tiết Volvo Bình Thạnh – đại lý chính thức của Volvo tại TP.HCM. Cập nhật mới nhất bảng giá các dòng xe Volvo chính hãng. Đừng bỏ lỡ cơ hội mua xe Volvo trả góp với lãi suất hấp dẫn. Xe điện Volvo EC40 – Thiết kế hiện đại, vận hành mạnh mẽ. Lái thử ngay Volvo XC60 Ultra để trải nghiệm cảm giác lái tuyệt vời. XC60 Plug-in Hybrid Ultra - giải pháp xe sang thân thiện với môi trường. Mua xe tại Volvo Bình Thạnh để nhận nhiều ưu đãi hấp dẫn. Bạn đang tìm hiểu giá xe Volvo mới nhất năm 2025? Hỗ trợ trả góp lên đến 80% giá trị xe Volvo. EC40 – mẫu SUV điện thu hút nhiều sự quan tâm từ người tiêu dùng. Khám phá các tính năng của Volvo XC60 Ultra trong tầm giá hơn 2 tỷ đồng. XC60 Plug-in Hybrid mang lại sự kết hợp giữa hiệu suất và tiết kiệm nhiên liệu. Đăng ký nhận báo giá tại đại lý Volvo Bình Thạnh ngay hôm nay! Đừng quên xem bảng giá Volvo cập nhật mỗi tháng. Mua xe Volvo trả góp chỉ cần trước 20% giá trị xe. Lựa chọn Volvo EC40 – mẫu xe không khí thải cho đô thị hiện đại. XC60 Ultra sở hữu nội thất sang trọng và hệ thống an toàn vượt trội. Khám phá Volvo XC60 Hybrid - sự kết hợp hoàn hảo giữa hiệu năng và công nghệ. Ghé thăm Volvo Bình Thạnh để lái thử các dòng xe mới nhất. Bạn đang phân vân lựa chọn dòng xe? Xem ngay bảng giá xe Volvo để có quyết định phù hợp. Volvo trả góp – Lựa chọn thông minh cho khách hàng tài chính linh hoạt. Giá xe điện Volvo EC40 hiện đang rất cạnh tranh. Tại sao nên chọn XC60 Ultra? Bởi vì nó có hệ thống lái bán tự động tiên tiến. Bạn có biết XC60 Plug-in Hybrid Ultra có khả năng vận hành bằng điện đến 80km? Đại lý Volvo Bình Thạnh chuyên cung cấp các dòng xe Volvo nhập khẩu chính hãng. Tư vấn bảng giá Volvo miễn phí qua hotline và showroom. Chương trình ưu đãi trả góp Volvo từ 0% lãi suất. Xe Volvo EC40 đạt tiêu chuẩn an toàn châu Âu. XC60 Ultra là mẫu SUV lý tưởng cho gia đình trẻ. Lựa chọn XC60 Plug-in Hybrid Ultra giúp tiết kiệm chi phí nhiên liệu dài hạn. Volvo Bình Thạnh có đội ngũ tư vấn tận tâm, chuyên nghiệp. Khám phá chi tiết giá xe Volvo từng phiên bản. Hồ sơ mua xe trả góp được hỗ trợ xử lý nhanh chóng. Xe điện Volvo EC40 – Lựa chọn lý tưởng cho lối sống xanh. XC60 Ultra đi kèm hệ thống giải trí hiện đại. Mẫu xe Volvo XC60 Hybrid Ultra phù hợp cả đi phố và đường trường. Liên hệ Volvo Bình Thạnh để được tư vấn kỹ hơn. Tìm hiểu giá lăn bánh xe Volvo tại TP.HCM. Ưu đãi lãi suất 0% khi mua xe Volvo trong tháng này. Chọn Volvo EC40 để tận hưởng công nghệ tự lái mới nhất. XC60 Ultra trang bị nhiều tính năng an toàn chủ động. Xe hybrid Volvo XC60 Plug-in Hybrid Ultra đang được khách hàng ưu tiên lựa chọn.